From 66e604b40e16e1a7b42c19617d598296f410bb5c Mon Sep 17 00:00:00 2001 From: "chao.an" Date: Thu, 9 Dec 2021 17:40:50 +0800 Subject: [PATCH] cortex-m/hardfault: add usage-fault handler Signed-off-by: chao.an --- arch/arm/Kconfig | 19 +++++ arch/arm/src/armv7-m/arm_usagefault.c | 115 ++++++++++++++++++++++++++ arch/arm/src/armv8-m/arm_usagefault.c | 115 ++++++++++++++++++++++++++ arch/arm/src/common/arm_internal.h | 1 + 4 files changed, 250 insertions(+) create mode 100644 arch/arm/src/armv7-m/arm_usagefault.c create mode 100644 arch/arm/src/armv8-m/arm_usagefault.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index d897ddc226..bae94014c0 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -594,6 +594,7 @@ config ARCH_CORTEXM3 select ARCH_HAVE_HARDFAULT_DEBUG select ARCH_HAVE_MEMFAULT_DEBUG select ARCH_HAVE_BUSFAULT_DEBUG + select ARCH_HAVE_USAGEFAULT_DEBUG config ARCH_CORTEXM4 bool @@ -609,6 +610,7 @@ config ARCH_CORTEXM4 select ARCH_HAVE_HARDFAULT_DEBUG select ARCH_HAVE_MEMFAULT_DEBUG select ARCH_HAVE_BUSFAULT_DEBUG + select ARCH_HAVE_USAGEFAULT_DEBUG config ARCH_CORTEXM7 bool @@ -625,6 +627,7 @@ config ARCH_CORTEXM7 select ARCH_HAVE_HARDFAULT_DEBUG select ARCH_HAVE_MEMFAULT_DEBUG select ARCH_HAVE_BUSFAULT_DEBUG + select ARCH_HAVE_USAGEFAULT_DEBUG config ARCH_ARMV7A bool @@ -734,6 +737,7 @@ config ARCH_CORTEXM33 select ARCH_HAVE_HARDFAULT_DEBUG select ARCH_HAVE_MEMFAULT_DEBUG select ARCH_HAVE_BUSFAULT_DEBUG + select ARCH_HAVE_USAGEFAULT_DEBUG config ARCH_CORTEXM35P bool @@ -749,6 +753,7 @@ config ARCH_CORTEXM35P select ARCH_HAVE_HARDFAULT_DEBUG select ARCH_HAVE_MEMFAULT_DEBUG select ARCH_HAVE_BUSFAULT_DEBUG + select ARCH_HAVE_USAGEFAULT_DEBUG config ARCH_CORTEXM55 bool @@ -764,6 +769,7 @@ config ARCH_CORTEXM55 select ARCH_HAVE_HARDFAULT_DEBUG select ARCH_HAVE_MEMFAULT_DEBUG select ARCH_HAVE_BUSFAULT_DEBUG + select ARCH_HAVE_USAGEFAULT_DEBUG config ARCH_FAMILY string @@ -986,6 +992,19 @@ config DEBUG_BUSFAULT output is sometimes helpful when debugging difficult bus fault problems, but may be more than you typically want to see. +config ARCH_HAVE_USAGEFAULT_DEBUG + bool + default n + +config DEBUG_USAGEFAULT + bool "Verbose Usage-Fault Debug" + default n + depends on ARCH_HAVE_USAGEFAULT_DEBUG && DEBUG_ALERT + ---help--- + Enables verbose debug output when a usage fault is occurs. This verbose + output is sometimes helpful when debugging difficult usage fault problems, + but may be more than you typically want to see. + config ARM_SEMIHOSTING_SYSLOG bool "Semihosting SYSLOG support" select ARCH_SYSLOG diff --git a/arch/arm/src/armv7-m/arm_usagefault.c b/arch/arm/src/armv7-m/arm_usagefault.c new file mode 100644 index 0000000000..9a759ccdb3 --- /dev/null +++ b/arch/arm/src/armv7-m/arm_usagefault.c @@ -0,0 +1,115 @@ +/**************************************************************************** + * arch/arm/src/armv7-m/arm_usagefault.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "arm_arch.h" +#include "nvic.h" +#include "arm_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_USAGEFAULT +# define ufalert(format, ...) _alert(format, ##__VA_ARGS__) +#else +# define ufalert(x...) +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: arm_usagefault + * + * Description: + * This is Usage Fault exception handler. It also catches SVC call + * exceptions that are performed in bad contexts. + * + ****************************************************************************/ + +int arm_usagefault(int irq, FAR void *context, FAR void *arg) +{ + uint32_t cfsr = getreg32(NVIC_CFAULTS); + + /* Dump some usage fault info */ + + ufalert("PANIC!!! Usage Fault:\n"); + ufalert("\tIRQ: %d regs: %p\n", irq, context); + ufalert("\tBASEPRI: %08x PRIMASK: %08x IPSR: %08x CONTROL: %08x\n", + getbasepri(), getprimask(), getipsr(), getcontrol()); + ufalert("\tCFSR: %08x HFSR: %08x DFSR: %08x BFAR: %08x AFSR: %08x\n", + cfsr, getreg32(NVIC_HFAULTS), getreg32(NVIC_DFAULTS), + getreg32(NVIC_BFAULT_ADDR), getreg32(NVIC_AFAULTS)); + + ufalert("Usage Fault Reason:\n"); + if (cfsr & NVIC_CFAULTS_UNDEFINSTR) + { + ufalert("\tUndefined instruction\n"); + } + + if (cfsr & NVIC_CFAULTS_INVSTATE) + { + ufalert("\tInvalid state\n"); + } + + if (cfsr & NVIC_CFAULTS_INVPC) + { + ufalert("\tInvalid PC load, " + "caused by an invalid PC load by EXC_RETURN\n"); + } + + if (cfsr & NVIC_CFAULTS_NOCP) + { + ufalert("\tNo Coprocessor\n"); + } + + if (cfsr & NVIC_CFAULTS_STKOF) + { + ufalert("\tStack Overflow\n"); + } + + if (cfsr & NVIC_CFAULTS_UNALIGNED) + { + ufalert("\tUnaligned access\n"); + } + + if (cfsr & NVIC_CFAULTS_DIVBYZERO) + { + ufalert("\tDivide by zero\n"); + } + + up_irq_save(); + PANIC(); + return OK; +} diff --git a/arch/arm/src/armv8-m/arm_usagefault.c b/arch/arm/src/armv8-m/arm_usagefault.c new file mode 100644 index 0000000000..8f82112e66 --- /dev/null +++ b/arch/arm/src/armv8-m/arm_usagefault.c @@ -0,0 +1,115 @@ +/**************************************************************************** + * arch/arm/src/armv8-m/arm_usagefault.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "arm_arch.h" +#include "nvic.h" +#include "arm_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_USAGEFAULT +# define ufalert(format, ...) _alert(format, ##__VA_ARGS__) +#else +# define ufalert(x...) +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: arm_usagefault + * + * Description: + * This is Usage Fault exception handler. It also catches SVC call + * exceptions that are performed in bad contexts. + * + ****************************************************************************/ + +int arm_usagefault(int irq, FAR void *context, FAR void *arg) +{ + uint32_t cfsr = getreg32(NVIC_CFAULTS); + + /* Dump some usage fault info */ + + ufalert("PANIC!!! Usage Fault:\n"); + ufalert("\tIRQ: %d regs: %p\n", irq, context); + ufalert("\tBASEPRI: %08x PRIMASK: %08x IPSR: %08x CONTROL: %08x\n", + getbasepri(), getprimask(), getipsr(), getcontrol()); + ufalert("\tCFSR: %08x HFSR: %08x DFSR: %08x BFAR: %08x AFSR: %08x\n", + cfsr, getreg32(NVIC_HFAULTS), getreg32(NVIC_DFAULTS), + getreg32(NVIC_BFAULT_ADDR), getreg32(NVIC_AFAULTS)); + + ufalert("Usage Fault Reason:\n"); + if (cfsr & NVIC_CFAULTS_UNDEFINSTR) + { + ufalert("\tUndefined instruction\n"); + } + + if (cfsr & NVIC_CFAULTS_INVSTATE) + { + ufalert("\tInvalid state\n"); + } + + if (cfsr & NVIC_CFAULTS_INVPC) + { + ufalert("\tInvalid PC load, " + "caused by an invalid PC load by EXC_RETURN\n"); + } + + if (cfsr & NVIC_CFAULTS_NOCP) + { + ufalert("\tNo Coprocessor\n"); + } + + if (cfsr & NVIC_CFAULTS_STKOF) + { + ufalert("\tStack Overflow\n"); + } + + if (cfsr & NVIC_CFAULTS_UNALIGNED) + { + ufalert("\tUnaligned access\n"); + } + + if (cfsr & NVIC_CFAULTS_DIVBYZERO) + { + ufalert("\tDivide by zero\n"); + } + + up_irq_save(); + PANIC(); + return OK; +} diff --git a/arch/arm/src/common/arm_internal.h b/arch/arm/src/common/arm_internal.h index 5ee5707417..457a146976 100644 --- a/arch/arm/src/common/arm_internal.h +++ b/arch/arm/src/common/arm_internal.h @@ -344,6 +344,7 @@ int arm_hardfault(int irq, FAR void *context, FAR void *arg); int arm_memfault(int irq, FAR void *context, FAR void *arg); int arm_busfault(int irq, FAR void *context, FAR void *arg); +int arm_usagefault(int irq, FAR void *context, FAR void *arg); # endif /* CONFIG_ARCH_CORTEXM3,4,7 */