diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index a768a79170..56b9a4f811 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -879,6 +879,34 @@ config ARM_MPU_NREGIONS ---help--- This is the number of protection regions supported by the MPU. +config ARM_MPU_RESET + bool "MPU Reset before MPU initialization" + default n + depends on ARM_MPU + ---help--- + Configures the MPU initialization sequence to disable the MPU + before configuring it. + + This may be needed in a system with a bootloader that has + configured the MPU prior to running NuttX. This may be all that is + needed to allow booting if the previous MPU configuration allow + the system to execute the MPU initialization code. If not use + ARM_MPU_EARLY_RESET. + +config ARM_MPU_EARLY_RESET + bool "MPU Early Reset" + default n + depends on ARCH_HAVE_MPU + ---help--- + Configures the early system initialization sequence to disable the MPU. + + This may be needed in a system with a bootloader that has + configured the MPU prior to running NuttX. This is useful if the system + faults during bbs, or data initialization or before the + stm32_mpuinitialize can be called. + + Note: This can be used without MPU Support enabled. + config ARCH_HAVE_LOWVECTORS bool diff --git a/arch/arm/src/armv7-m/arm_mpu.c b/arch/arm/src/armv7-m/arm_mpu.c index b24166114b..7a35108495 100644 --- a/arch/arm/src/armv7-m/arm_mpu.c +++ b/arch/arm/src/armv7-m/arm_mpu.c @@ -177,6 +177,33 @@ static inline uint32_t mpu_subregion_ls(size_t offset, uint8_t l2size) return g_ls_regionmask[nsrs]; } +/**************************************************************************** + * Name: mpu_reset_internal + * + * Description: + * Resets the MPU to disabled. + * + ****************************************************************************/ + +#if defined(CONFIG_MPU_RESET) || defined(CONFIG_ARM_MPU_EARLY_RESET) +static void mpu_reset_internal() +{ + int region; + int regions; + regions = (getreg32(MPU_TYPE) & MPU_TYPE_DREGION_MASK) + >> MPU_TYPE_DREGION_SHIFT; + + for (region = 0; region < regions; region++) + { + putreg32(region, MPU_RNR); + putreg32(0, MPU_RASR); + putreg32(0, MPU_RBAR); + } + + putreg32(0, MPU_CTRL); +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -387,3 +414,33 @@ void mpu_configure_region(uintptr_t base, size_t size, flags; putreg32(regval, MPU_RASR); } + +/**************************************************************************** + * Name: mpu_reset + * + * Description: + * Conditional public interface that resets the MPU to disabled during + * MPU initialization. + * + ****************************************************************************/ +#if defined(CONFIG_MPU_RESET) +void mpu_reset() +{ + mpu_reset_internal(); +} +#endif + +/**************************************************************************** + * Name: mpu_early_reset + * + * Description: + * Conditional public interface that resets the MPU to disabled immediately + * after reset. + * + ****************************************************************************/ +#if defined(CONFIG_ARM_MPU_EARLY_RESET) +void mpu_early_reset() +{ + mpu_reset_internal(); +} +#endif diff --git a/arch/arm/src/armv7-m/mpu.h b/arch/arm/src/armv7-m/mpu.h index 2d8fb885bd..870fea6207 100644 --- a/arch/arm/src/armv7-m/mpu.h +++ b/arch/arm/src/armv7-m/mpu.h @@ -132,6 +132,36 @@ # define MPU_RASR_AP_RORO (6 << MPU_RASR_AP_SHIFT) /* P:RO U:RO */ # define MPU_RASR_XN (1 << 28) /* Bit 28: Instruction access disable */ +/**************************************************************************** + * Name: mpu_reset + * + * Description: + * Conditional public interface that resets the MPU to disabled during + * MPU initialization. + * + ****************************************************************************/ + +#if defined(CONFIG_MPU_RESET) +void mpu_reset(void); +#else +# define mpu_reset() do { } while (0) +#endif + +/**************************************************************************** + * Name: mpu_early_reset + * + * Description: + * Conditional public interface that resets the MPU to disabled immediately + * after reset. + * + ****************************************************************************/ + +#if defined(CONFIG_ARM_MPU_EARLY_RESET) +void mpu_early_reset(void); +#else +# define mpu_early_reset() do { } while (0) +#endif + #ifdef CONFIG_ARM_MPU /**************************************************************************** diff --git a/arch/arm/src/armv7-r/arm_mpu.c b/arch/arm/src/armv7-r/arm_mpu.c index 5fd372339b..2023909243 100644 --- a/arch/arm/src/armv7-r/arm_mpu.c +++ b/arch/arm/src/armv7-r/arm_mpu.c @@ -177,6 +177,33 @@ static inline uint32_t mpu_subregion_ls(size_t offset, uint8_t l2size) return g_ls_regionmask[nsrs]; } +/**************************************************************************** + * Name: mpu_reset_internal + * + * Description: + * Resets the MPU to disabled. + * + ****************************************************************************/ + +#if defined(CONFIG_MPU_RESET) || defined(CONFIG_ARM_MPU_EARLY_RESET) +static void mpu_reset_internal() +{ + int region; + int regions; + regions = (getreg32(MPU_TYPE) & MPU_TYPE_DREGION_MASK) + >> MPU_TYPE_DREGION_SHIFT; + + for (region = 0; region < regions; region++) + { + putreg32(region, MPU_RNR); + putreg32(0, MPU_RASR); + putreg32(0, MPU_RBAR); + } + + putreg32(0, MPU_CTRL); +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -300,3 +327,33 @@ uint32_t mpu_subregion(uintptr_t base, size_t size, uint8_t l2size) ret |= mpu_subregion_ls(offset, l2size); return ret; } + +/**************************************************************************** + * Name: mpu_reset + * + * Description: + * Conditional public interface that resets the MPU to disabled during + * MPU initialization. + * + ****************************************************************************/ +#if defined(CONFIG_MPU_RESET) +void mpu_reset() +{ + mpu_reset_internal(); +} +#endif + +/**************************************************************************** + * Name: mpu_early_reset + * + * Description: + * Conditional public interface that resets the MPU to disabled immediately + * after reset. + * + ****************************************************************************/ +#if defined(CONFIG_ARM_MPU_EARLY_RESET) +void mpu_early_reset() +{ + mpu_reset_internal(); +} +#endif diff --git a/arch/arm/src/armv7-r/mpu.h b/arch/arm/src/armv7-r/mpu.h index e4ccc98735..5824353908 100644 --- a/arch/arm/src/armv7-r/mpu.h +++ b/arch/arm/src/armv7-r/mpu.h @@ -120,6 +120,36 @@ extern "C" #define EXTERN extern #endif +/**************************************************************************** + * Name: mpu_reset + * + * Description: + * Conditional public interface that resets the MPU to disabled during + * MPU initialization. + * + ****************************************************************************/ + +#if defined(CONFIG_MPU_RESET) +void mpu_reset(void); +#else +# define mpu_reset() do { } while (0) +#endif + +/**************************************************************************** + * Name: mpu_early_reset + * + * Description: + * Conditional public interface that resets the MPU to disabled immediately + * after reset. + * + ****************************************************************************/ + +#if defined(CONFIG_ARM_MPU_EARLY_RESET) +void mpu_early_reset(void); +#else +# define mpu_early_reset() do { } while (0) +#endif + /**************************************************************************** * Name: mpu_allocregion * diff --git a/arch/arm/src/armv8-m/arm_mpu.c b/arch/arm/src/armv8-m/arm_mpu.c index 29bb63df1e..50ae4ff63c 100644 --- a/arch/arm/src/armv8-m/arm_mpu.c +++ b/arch/arm/src/armv8-m/arm_mpu.c @@ -71,6 +71,33 @@ unsigned int mpu_allocregion(void) return (unsigned int)g_region++; } +/**************************************************************************** + * Name: mpu_reset_internal + * + * Description: + * Resets the MPU to disabled. + * + ****************************************************************************/ + +#if defined(CONFIG_MPU_RESET) || defined(CONFIG_ARM_MPU_EARLY_RESET) +static void mpu_reset_internal() +{ + int region; + int regions; + regions = (getreg32(MPU_TYPE) & MPU_TYPE_DREGION_MASK) + >> MPU_TYPE_DREGION_SHIFT; + + for (region = 0; region < regions; region++) + { + putreg32(region, MPU_RNR); + putreg32(0, MPU_RASR); + putreg32(0, MPU_RBAR); + } + + putreg32(0, MPU_CTRL); +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -148,3 +175,33 @@ void mpu_configure_region(uintptr_t base, size_t size, putreg32(base | flags1, MPU_RBAR); putreg32(limit | flags2 | MPU_RLAR_ENABLE, MPU_RLAR); } + +/**************************************************************************** + * Name: mpu_reset + * + * Description: + * Conditional public interface that resets the MPU to disabled during + * MPU initialization. + * + ****************************************************************************/ +#if defined(CONFIG_MPU_RESET) +void mpu_reset() +{ + mpu_reset_internal(); +} +#endif + +/**************************************************************************** + * Name: mpu_early_reset + * + * Description: + * Conditional public interface that resets the MPU to disabled immediately + * after reset. + * + ****************************************************************************/ +#if defined(CONFIG_ARM_MPU_EARLY_RESET) +void mpu_early_reset() +{ + mpu_reset_internal(); +} +#endif diff --git a/arch/arm/src/armv8-m/mpu.h b/arch/arm/src/armv8-m/mpu.h index 4e793dedce..428a06aff7 100644 --- a/arch/arm/src/armv8-m/mpu.h +++ b/arch/arm/src/armv8-m/mpu.h @@ -171,6 +171,36 @@ MPU_MAIR_INNER_NT | MPU_MAIR_INNER_WB | \ MPU_MAIR_INNER_RA | MPU_MAIR_INNER_WA) +/**************************************************************************** + * Name: mpu_reset + * + * Description: + * Conditional public interface that resets the MPU to disabled during + * MPU initialization. + * + ****************************************************************************/ + +#if defined(CONFIG_MPU_RESET) +void mpu_reset(void); +#else +# define mpu_reset() do { } while (0) +#endif + +/**************************************************************************** + * Name: mpu_early_reset + * + * Description: + * Conditional public interface that resets the MPU to disabled immediately + * after reset. + * + ****************************************************************************/ + +#if defined(CONFIG_ARM_MPU_EARLY_RESET) +void mpu_early_reset(void); +#else +# define mpu_early_reset() do { } while (0) +#endif + #ifdef CONFIG_ARM_MPU /****************************************************************************