From 666657b7153b5453fa7e0cf63fbbb2910f02b15d Mon Sep 17 00:00:00 2001 From: "pradeep.ns" Date: Wed, 28 Jun 2017 00:07:50 +0530 Subject: [PATCH] Display Interrupts information to user If CONFIG_ENABLE_IRQINFO is enabled, This patch would display the number of registerd interrupts, it's occurrences in the system and it's isr information. This feature works for flat build ie BUILD_PROTECTED = n and when TASH shell is enabled This debug feature is required for following important reasons 1) To know how many interrupts have been configured in the system 2) To know which interrupt lines have been configured and it's corresponding ISR name 3) To debug the system hogging issues if it's caused by any spurious interrupts. 4) This can be enhanced in future to know which interrupts are set for cpu affinity and it's occurrences on each cpu. Verification: TASH>>irqinfo INDEX | IRQ_NUM | INT_COUNT | ISR_NAME -------|---------|-----------|---------- 1 | 36 | 0 | gic_interrupt 2 | 37 | 0 | gic_interrupt 3 | 58 | 23289 | up_timerisr 4 | 90 | 374 | up_interrupt Without tash, one can enable CONFIG_DEBUG_IRQ_INFO to know the irq information for remote debugging Following changes are done: 1) Introduced 2 new variables a) count and b) irq_name 2) Updated the irq_name during irq_attach (ISR name ) and irq_detach ( NULL ) 3) Reset the count to 0 while irq_attach and irq_detach is called 4) displayed the output to console when irqinfo is executed from TASH 5) if CONFIG_ENABLE_IRQINFO is not enabled, still irqinfo would be updated if CONFIG_DEBUG_IRQ_INFO is enabled and this can be used for offline debug Signed-off-by: pradeep.ns --- apps/system/utils/Kconfig | 9 ++++- apps/system/utils/Makefile | 4 +++ apps/system/utils/kdbg_commands.h | 4 +++ apps/system/utils/kdbg_irqinfo.c | 31 +++++++++++++++++ apps/system/utils/kernelcmd.c | 3 ++ os/Kconfig | 6 ++++ os/include/tinyara/irq.h | 24 ++++++++++++- os/kernel/irq/Make.defs | 4 +++ os/kernel/irq/irq.h | 7 ++++ os/kernel/irq/irq_attach.c | 15 ++++++++ os/kernel/irq/irq_dispatch.c | 3 ++ os/kernel/irq/irq_info.c | 72 +++++++++++++++++++++++++++++++++++++++ os/kernel/irq/irq_initialize.c | 5 ++- 13 files changed, 184 insertions(+), 3 deletions(-) create mode 100644 apps/system/utils/kdbg_irqinfo.c create mode 100644 os/kernel/irq/irq_info.c diff --git a/apps/system/utils/Kconfig b/apps/system/utils/Kconfig index 890b7d9..e7b35c9 100644 --- a/apps/system/utils/Kconfig +++ b/apps/system/utils/Kconfig @@ -81,6 +81,14 @@ config ENABLE_HEAPINFO ---help--- Show information about memory status per thread +config ENABLE_IRQINFO + bool "irqinfo" + default n + depends on TASH && !BUILD_PROTECTED && !BUILD_KERNEL + select DEBUG_IRQ_INFO if DEBUG + ---help--- + List the registered interrupts, it's occurrence counts and corresponding isr. + if !DISABLE_SIGNALS config ENABLE_KILL bool "kill" @@ -136,4 +144,3 @@ config ENABLE_UPTIME default y ---help--- print how long the system has been running - diff --git a/apps/system/utils/Makefile b/apps/system/utils/Makefile index fc76d96..1336f3f 100644 --- a/apps/system/utils/Makefile +++ b/apps/system/utils/Makefile @@ -118,6 +118,10 @@ ifeq ($(CONFIG_ENABLE_HEAPINFO),y) CSRCS += kdbg_heapinfo.c endif +ifeq ($(CONFIG_ENABLE_IRQINFO),y) +CSRCS += kdbg_irqinfo.c +endif + ifneq ($(CONFIG_DISABLE_SIGNALS),y) ifeq ($(CONFIG_ENABLE_KILL),y) CSRCS += kdbg_kill.c diff --git a/apps/system/utils/kdbg_commands.h b/apps/system/utils/kdbg_commands.h index 80e5012..f4da48e 100644 --- a/apps/system/utils/kdbg_commands.h +++ b/apps/system/utils/kdbg_commands.h @@ -51,6 +51,10 @@ int kdbg_free(int argc, char **args); int kdbg_heapinfo(int argc, char **args); #endif +#if defined(CONFIG_ENABLE_IRQINFO) +int kdbg_irqinfo(int argc, char **args); +#endif + #ifndef CONFIG_DISABLE_SIGNALS #if defined(CONFIG_ENABLE_KILL) int kdbg_kill(int argc, char **args); diff --git a/apps/system/utils/kdbg_irqinfo.c b/apps/system/utils/kdbg_irqinfo.c new file mode 100644 index 0000000..ba3366d --- /dev/null +++ b/apps/system/utils/kdbg_irqinfo.c @@ -0,0 +1,31 @@ +/**************************************************************************** + * + * Copyright 2017 Samsung Electronics All Rights Reserved. + * + * Licensed 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. + * + ****************************************************************************/ + +#include + + +int kdbg_irqinfo(int argc, char **args) +{ +#ifdef CONFIG_DEBUG_IRQ_INFO + irq_info(); + return OK; +#else +#error "Note : CONFIG_ENABLE_IRQINFO is Enabled but CONFIG_DEBUG and CONFIG_DEBUG_IRQ_INFO is not enabled" + return ERROR; +#endif +} diff --git a/apps/system/utils/kernelcmd.c b/apps/system/utils/kernelcmd.c index 1730640..6f010fa 100644 --- a/apps/system/utils/kernelcmd.c +++ b/apps/system/utils/kernelcmd.c @@ -40,6 +40,9 @@ const static tash_cmdlist_t kdbg_cmds[] = { #if defined(CONFIG_ENABLE_HEAPINFO) {"heapinfo", kdbg_heapinfo, TASH_EXECMD_SYNC}, #endif +#if defined(CONFIG_ENABLE_IRQINFO) + {"irqinfo", kdbg_irqinfo, TASH_EXECMD_SYNC}, +#endif #if defined(CONFIG_ENABLE_KILL) {"kill", kdbg_kill, TASH_EXECMD_SYNC}, #endif diff --git a/os/Kconfig b/os/Kconfig index 525471b..b084f61 100644 --- a/os/Kconfig +++ b/os/Kconfig @@ -824,6 +824,12 @@ config DEBUG_IRQ that here is a problem with that logic. On some platforms, this option may even cause crashes! Use with care! +config DEBUG_IRQ_INFO + bool "Interrupt Debug information" + default n + ---help--- + List the registered interrupts, it's occurrence count and corresponding isr. + config DEBUG_PAGING bool "Demand Paging Debug Output" default n diff --git a/os/include/tinyara/irq.h b/os/include/tinyara/irq.h index f973b79..bb8a7c0 100644 --- a/os/include/tinyara/irq.h +++ b/os/include/tinyara/irq.h @@ -68,9 +68,13 @@ */ #ifndef __ASSEMBLY__ +#ifdef CONFIG_DEBUG_IRQ_INFO +#define irq_attach(irq, handler, arg) irq_attach_withname(irq, handler, arg, #handler) +#define irq_detach(irq) irq_attach_withname(irq, NULL, NULL, NULL) +#else #define irq_detach(irq) irq_attach(irq, NULL, NULL) #endif - +#endif /**************************************************************************** * Public Types ****************************************************************************/ @@ -110,7 +114,25 @@ extern "C" { * ****************************************************************************/ +#ifdef CONFIG_DEBUG_IRQ_INFO +int irq_attach_withname(int irq, xcpt_t isr, FAR void *arg, const char *name); +#else int irq_attach(int irq, xcpt_t isr, FAR void *arg); +#endif + +#ifdef CONFIG_DEBUG_IRQ_INFO + +/**************************************************************************** + * Name: irq_info + * + * Description: + * Display the registered IRQ numbers and it's isr details to user + * + ****************************************************************************/ + +void irq_info(void); + +#endif #undef EXTERN #ifdef __cplusplus diff --git a/os/kernel/irq/Make.defs b/os/kernel/irq/Make.defs index b2aa783..7241dbf 100644 --- a/os/kernel/irq/Make.defs +++ b/os/kernel/irq/Make.defs @@ -52,6 +52,10 @@ CSRCS += irq_initialize.c irq_attach.c irq_dispatch.c irq_unexpectedisr.c +ifeq ($(CONFIG_DEBUG_IRQ_INFO),y) +CSRCS += irq_info.c +endif + # Include irq build support DEPPATH += --dep-path irq diff --git a/os/kernel/irq/irq.h b/os/kernel/irq/irq.h index 440238a..483b239 100644 --- a/os/kernel/irq/irq.h +++ b/os/kernel/irq/irq.h @@ -66,6 +66,9 @@ /**************************************************************************** * Definitions ****************************************************************************/ +#ifdef CONFIG_DEBUG_IRQ_INFO +#define MAX_IRQNAME_SIZE 31 +#endif /**************************************************************************** * Public Type Declarations @@ -74,6 +77,10 @@ struct irq { xcpt_t handler; FAR void *arg; +#ifdef CONFIG_DEBUG_IRQ_INFO + char irq_name[MAX_IRQNAME_SIZE + 1]; /* Includes the terminating Null */ + size_t count; +#endif }; extern struct irq g_irqvector[NR_IRQS]; diff --git a/os/kernel/irq/irq_attach.c b/os/kernel/irq/irq_attach.c index ea6f46f..587fa27 100644 --- a/os/kernel/irq/irq_attach.c +++ b/os/kernel/irq/irq_attach.c @@ -93,7 +93,11 @@ * ****************************************************************************/ +#ifdef CONFIG_DEBUG_IRQ_INFO +int irq_attach_withname(int irq, xcpt_t isr, FAR void *arg, const char *name) +#else int irq_attach(int irq, xcpt_t isr, FAR void *arg) +#endif { #if NR_IRQS > 0 int ret = ERROR; @@ -133,6 +137,17 @@ int irq_attach(int irq, xcpt_t isr, FAR void *arg) g_irqvector[irq].handler = isr; g_irqvector[irq].arg = arg; +#ifdef CONFIG_DEBUG_IRQ_INFO + /* Reset the irq counter to 0 and it's applicable for both irq_attach and irq_detach */ + g_irqvector[irq].count = 0; + if (name != NULL) { + strncpy(g_irqvector[irq].irq_name, name, MAX_IRQNAME_SIZE); + g_irqvector[irq].irq_name[MAX_IRQNAME_SIZE] = '\0'; + } else { + /* irq_detach will set isr as NULL, thus name would be passed as NULL. Set the irq_name to Null */ + g_irqvector[irq].irq_name[0] = '\0'; + } +#endif irqrestore(state); ret = OK; } diff --git a/os/kernel/irq/irq_dispatch.c b/os/kernel/irq/irq_dispatch.c index db2eec6..e312578 100644 --- a/os/kernel/irq/irq_dispatch.c +++ b/os/kernel/irq/irq_dispatch.c @@ -109,6 +109,9 @@ void irq_dispatch(int irq, FAR void *context) } else { vector = g_irqvector[irq].handler; arg = g_irqvector[irq].arg; +#ifdef CONFIG_DEBUG_IRQ_INFO + g_irqvector[irq].count++; +#endif } #else vector = irq_unexpected_isr; diff --git a/os/kernel/irq/irq_info.c b/os/kernel/irq/irq_info.c new file mode 100644 index 0000000..5533412 --- /dev/null +++ b/os/kernel/irq/irq_info.c @@ -0,0 +1,72 @@ +/**************************************************************************** + * + * Copyright 2017 Samsung Electronics All Rights Reserved. + * + * Licensed 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 "irq/irq.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: irq_info + * + * Description: + * Display the registered IRQ information + * + ****************************************************************************/ + +void irq_info(void) +{ + uint16_t i; + uint16_t j; + + printf(" %5s | %7s | %9s | %3s \n", "INDEX", "IRQ_NUM", "INT_COUNT", "ISR_NAME"); + printf("-------|---------|-----------|----------\n"); + for (i = 0, j = 0; i < NR_IRQS; i++) { + if (g_irqvector[i].handler != irq_unexpected_isr) { + j++; + printf(" %5d | %7d | %9d | %s \n", j, i, g_irqvector[i].count, g_irqvector[i].irq_name); + } + } +} diff --git a/os/kernel/irq/irq_initialize.c b/os/kernel/irq/irq_initialize.c index fed3a14..75a6e88 100644 --- a/os/kernel/irq/irq_initialize.c +++ b/os/kernel/irq/irq_initialize.c @@ -98,10 +98,13 @@ void irq_initialize(void) { int i; + /* It will explicitly set all arguments of g_irqvector to 0 */ + + memset(g_irqvector, 0, sizeof(g_irqvector)); + /* Point all interrupt vectors to the unexpected interrupt */ for (i = 0; i < NR_IRQS; i++) { g_irqvector[i].handler = irq_unexpected_isr; - g_irqvector[i].arg = NULL; } } -- 2.7.4