From 90565cc75b4597097244b9b0e66d84038f92066c Mon Sep 17 00:00:00 2001 From: Matteo Golin Date: Wed, 19 Feb 2025 21:56:26 -0500 Subject: [PATCH] arch/arm/stm32h7: Add lazy FPU for STM32H7 ARMV7 single core chips Introduces LAZYFPU by enabling LSPEN and ASPEN for lazy stacking and automatic state preservation. FPU registers are no longer stored in XCPT registers (HW and SW) if LAZY FPU is enabled. Signed-off-by: Matteo Golin --- arch/arm/include/armv7-m/irq.h | 19 +++++++++++++++++- arch/arm/src/armv7-m/arm_fpuconfig.c | 30 ++++++++++++++++++++++++++++ arch/arm/src/stm32h7/Kconfig | 2 ++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/arch/arm/include/armv7-m/irq.h b/arch/arm/include/armv7-m/irq.h index 8c1cf80368c39..1f97aaaed1254 100644 --- a/arch/arm/include/armv7-m/irq.h +++ b/arch/arm/include/armv7-m/irq.h @@ -106,9 +106,17 @@ # define SW_FPU_REGS (0) #endif -/* The total number of registers saved by software */ +/* The total number of registers saved by software. + * If lazy FPU is enabled, save only integer registers. FPU registers are + * handled separately. + */ +#ifndef CONFIG_ARCH_LAZYFPU #define SW_XCPT_REGS (SW_INT_REGS + SW_FPU_REGS) +#else +#define SW_XCPT_REGS (SW_INT_REGS) +#endif + #define SW_XCPT_SIZE (4 * SW_XCPT_REGS) /* On entry into an IRQ, the hardware automatically saves the following @@ -153,7 +161,16 @@ # define HW_FPU_REGS (0) #endif +/* If lazy FPU is enabled, save only integer registers. FPU registers are + * handled separately. + */ + +#ifndef CONFIG_ARCH_LAZYFPU #define HW_XCPT_REGS (HW_INT_REGS + HW_FPU_REGS) +#else +#define HW_XCPT_REGS (HW_INT_REGS) +#endif + #define HW_XCPT_SIZE (4 * HW_XCPT_REGS) #define XCPTCONTEXT_REGS (HW_XCPT_REGS + SW_XCPT_REGS) diff --git a/arch/arm/src/armv7-m/arm_fpuconfig.c b/arch/arm/src/armv7-m/arm_fpuconfig.c index df1549afd7d13..a274c96eb4ba7 100644 --- a/arch/arm/src/armv7-m/arm_fpuconfig.c +++ b/arch/arm/src/armv7-m/arm_fpuconfig.c @@ -24,6 +24,8 @@ * Included Files ****************************************************************************/ +#include + #include "nvic.h" #include "arm_internal.h" @@ -56,6 +58,7 @@ * ****************************************************************************/ +#ifndef CONFIG_ARCH_LAZYFPU void arm_fpuconfig(void) { uint32_t regval; @@ -83,3 +86,30 @@ void arm_fpuconfig(void) regval |= NVIC_CPACR_CP_FULL(10) | NVIC_CPACR_CP_FULL(11); putreg32(regval, NVIC_CPACR); } +#else +void arm_fpuconfig(void) +{ + uint32_t regval; + + /* Clear CONTROL.FPCA so that we do not get the extended context frame + * with the volatile FP registers stacked in the saved context. + */ + + regval = getcontrol(); + regval &= ~CONTROL_FPCA; + setcontrol(regval); + + /* Enable lazy stacking (LSPEN) and automatic state preservation (ASPEN). + */ + + regval = getreg32(NVIC_FPCCR); + regval |= (NVIC_FPCCR_ASPEN | NVIC_FPCCR_LSPEN); + putreg32(regval, NVIC_FPCCR); + + /* Enable full access to CP10 and CP11 */ + + regval = getreg32(NVIC_CPACR); + regval |= NVIC_CPACR_CP_FULL(10) | NVIC_CPACR_CP_FULL(11); + putreg32(regval, NVIC_CPACR); +} +#endif diff --git a/arch/arm/src/stm32h7/Kconfig b/arch/arm/src/stm32h7/Kconfig index ff2b0444f91b3..1a46fdd31aca7 100644 --- a/arch/arm/src/stm32h7/Kconfig +++ b/arch/arm/src/stm32h7/Kconfig @@ -382,6 +382,7 @@ config STM32H7_STM32H7X3XX bool default n select ARCH_HAVE_FPU + select ARCH_HAVE_LAZYFPU select ARCH_HAVE_DPFPU select STM32H7_HAVE_LTDC select STM32H7_HAVE_ETHERNET @@ -396,6 +397,7 @@ config STM32H7_STM32H7B3XX bool default n select ARCH_HAVE_FPU + select ARCH_HAVE_LAZYFPU select ARCH_HAVE_DPFPU select STM32H7_HAVE_ETHERNET select STM32H7_HAVE_FMC