From 6be90b812d6f1f4249237fe18f065acc8738a06f Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Fri, 27 May 2022 13:14:31 +0200 Subject: [PATCH] [nrf toup] platform: nordic_nrf: Add option to initialize hardware to reset on boot Add an option to the nordic platforms to initialize the hardware state to the its reset values when the TF-M firmware is booting. The option is useful when the TF-M firmware image is chain-loaded, for example, a bootloader, and we need to guarantee that the internal states of the architecture core blocks are restored to the reset values. Signed-off-by: Joakim Andersson (cherry picked from commit 9f3911b8d3c0116d208e17789de4e9fd4b9ff0be) Signed-off-by: Joakim Andersson --- .../nordic_nrf/common/core/CMakeLists.txt | 12 +++++ .../nordic_nrf/common/core/config.cmake | 2 + .../target/nordic_nrf/common/core/hw_init.c | 53 +++++++++++++++++++ .../target/nordic_nrf/common/core/hw_init.h | 13 +++++ .../common/nrf5340/gcc/startup_nrf5340_s.S | 25 +++++++++ .../common/nrf9160/gcc/startup_nrf9160_s.S | 25 +++++++++ 6 files changed, 130 insertions(+) create mode 100644 platform/ext/target/nordic_nrf/common/core/hw_init.c create mode 100644 platform/ext/target/nordic_nrf/common/core/hw_init.h diff --git a/platform/ext/target/nordic_nrf/common/core/CMakeLists.txt b/platform/ext/target/nordic_nrf/common/core/CMakeLists.txt index cbfeb2e63..c8a3c91bd 100644 --- a/platform/ext/target/nordic_nrf/common/core/CMakeLists.txt +++ b/platform/ext/target/nordic_nrf/common/core/CMakeLists.txt @@ -77,6 +77,18 @@ target_sources(platform_s plat_test.c ) +if (NRF_HW_INIT_RESET_ON_BOOT) + target_sources(platform_s + PRIVATE + hw_init.c + ) + + target_compile_definitions(platform_s + PUBLIC + NRF_HW_INIT_RESET_ON_BOOT + ) +endif() + if(TFM_PARTITION_PLATFORM) target_sources(platform_s PRIVATE diff --git a/platform/ext/target/nordic_nrf/common/core/config.cmake b/platform/ext/target/nordic_nrf/common/core/config.cmake index af0540bc0..b18a1d157 100644 --- a/platform/ext/target/nordic_nrf/common/core/config.cmake +++ b/platform/ext/target/nordic_nrf/common/core/config.cmake @@ -20,3 +20,5 @@ set(NULL_POINTER_EXCEPTION_DETECTION FALSE CACHE BOOL set(PLATFORM_SLIH_IRQ_TEST_SUPPORT ON CACHE BOOL "Platform supports SLIH IRQ tests") set(PLATFORM_FLIH_IRQ_TEST_SUPPORT ON CACHE BOOL "Platform supports FLIH IRQ tests") + +set(NRF_HW_INIT_RESET_ON_BOOT CACHE BOOL OFF "Initialize internal architecture state at boot") diff --git a/platform/ext/target/nordic_nrf/common/core/hw_init.c b/platform/ext/target/nordic_nrf/common/core/hw_init.c new file mode 100644 index 000000000..6a5af353a --- /dev/null +++ b/platform/ext/target/nordic_nrf/common/core/hw_init.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include "array.h" + +/* This routine clears all ARM MPU region configuration. */ +static void hw_init_mpu(void) +{ + const int num_regions = + ((MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos); + + for (int i = 0; i < num_regions; i++) { + ARM_MPU_ClrRegion(i); + } +} + +/* This routine resets Cortex-M system control block components and core + * registers. + */ +void hw_init_reset_on_boot(void) +{ + /* Disable interrupts */ + __disable_irq(); + + /* Reset exception and interrupt mask state (PRIMASK handled by + * __enable_irq below) + */ + __set_FAULTMASK(0); + __set_BASEPRI(0); + + /* Clear MPU region configuration */ + hw_init_mpu(); + + /* Disable NVIC interrupts */ + for (int i = 0; i < ARRAY_SIZE(NVIC->ICER); i++) { + NVIC->ICER[i] = 0xFFFFFFFF; + } + /* Clear pending NVIC interrupts */ + for (int i = 0; i < ARRAY_SIZE(NVIC->ICPR); i++) { + NVIC->ICPR[i] = 0xFFFFFFFF; + } + + /* Restore Interrupts */ + __enable_irq(); + + __DSB(); + __ISB(); +} diff --git a/platform/ext/target/nordic_nrf/common/core/hw_init.h b/platform/ext/target/nordic_nrf/common/core/hw_init.h new file mode 100644 index 000000000..c4bed4e3b --- /dev/null +++ b/platform/ext/target/nordic_nrf/common/core/hw_init.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef HW_INIT_H__ +#define HW_INIT_H__ + +#define _SCS_BASE_ADDR 0xE000E000 +#define _SCS_MPU_CTRL (_SCS_BASE_ADDR + 0xd94) + +#endif /* HW_INIT_H__*/ diff --git a/platform/ext/target/nordic_nrf/common/nrf5340/gcc/startup_nrf5340_s.S b/platform/ext/target/nordic_nrf/common/nrf5340/gcc/startup_nrf5340_s.S index df7d5797f..a6ea819cb 100644 --- a/platform/ext/target/nordic_nrf/common/nrf5340/gcc/startup_nrf5340_s.S +++ b/platform/ext/target/nordic_nrf/common/nrf5340/gcc/startup_nrf5340_s.S @@ -22,6 +22,7 @@ */ #include "tfm_plat_config.h" +#include "hw_init.h" .syntax unified .arch armv8-m.main @@ -128,6 +129,30 @@ __Vectors: .globl Reset_Handler .type Reset_Handler, %function Reset_Handler: + +/* If the ARM core status registers and system blocks are not in their initial + * reset values then reset these first before booting. + */ +#ifdef NRF_HW_INIT_RESET_ON_BOOT + movs r0, #0 + + /* Reset CONTROL register */ + msr CONTROL, r0 + isb + + /* Clear SPLIM registers */ + msr MSPLIM, r0 + msr PSPLIM, r0 + + /* Disable MPU */ + ldr r1, =_SCS_MPU_CTRL + str r0, [r1] + dsb + + /* Initialize core architecture registers and system blocks */ + bl hw_init_reset_on_boot +#endif /* NRF_HW_INIT_RESET_ON_BOOT */ + /* Firstly it copies data from read only memory to RAM. There are two schemes * to copy. One can copy more than one sections. Another can only copy * one section. The former scheme needs more instructions and read-only diff --git a/platform/ext/target/nordic_nrf/common/nrf9160/gcc/startup_nrf9160_s.S b/platform/ext/target/nordic_nrf/common/nrf9160/gcc/startup_nrf9160_s.S index d143651b1..b21a55546 100644 --- a/platform/ext/target/nordic_nrf/common/nrf9160/gcc/startup_nrf9160_s.S +++ b/platform/ext/target/nordic_nrf/common/nrf9160/gcc/startup_nrf9160_s.S @@ -22,6 +22,7 @@ */ #include "tfm_plat_config.h" +#include "hw_init.h" .syntax unified .arch armv8-m.main @@ -124,6 +125,30 @@ __Vectors: .globl Reset_Handler .type Reset_Handler, %function Reset_Handler: + +/* If the ARM core status registers and system blocks are not in their initial + * reset values then reset these first before booting. + */ +#ifdef NRF_HW_INIT_RESET_ON_BOOT + movs r0, #0 + + /* Reset CONTROL register */ + msr CONTROL, r0 + isb + + /* Clear SPLIM registers */ + msr MSPLIM, r0 + msr PSPLIM, r0 + + /* Disable MPU */ + ldr r1, =_SCS_MPU_CTRL + str r0, [r1] + dsb + + /* Initialize core architecture registers and system blocks */ + bl hw_init_reset_on_boot +#endif /* NRF_HW_INIT_RESET_ON_BOOT */ + /* Firstly it copies data from read only memory to RAM. There are two schemes * to copy. One can copy more than one sections. Another can only copy * one section. The former scheme needs more instructions and read-only