Display Interrupts information to user
authorpradeep.ns <pradeep.ns@samsung.com>
Tue, 27 Jun 2017 18:37:50 +0000 (00:07 +0530)
committerpradeep.ns <pradeep.ns@samsung.com>
Thu, 3 Aug 2017 11:43:57 +0000 (17:13 +0530)
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 <pradeep.ns@samsung.com>
13 files changed:
apps/system/utils/Kconfig
apps/system/utils/Makefile
apps/system/utils/kdbg_commands.h
apps/system/utils/kdbg_irqinfo.c [new file with mode: 0644]
apps/system/utils/kernelcmd.c
os/Kconfig
os/include/tinyara/irq.h
os/kernel/irq/Make.defs
os/kernel/irq/irq.h
os/kernel/irq/irq_attach.c
os/kernel/irq/irq_dispatch.c
os/kernel/irq/irq_info.c [new file with mode: 0644]
os/kernel/irq/irq_initialize.c

index 890b7d9..e7b35c9 100644 (file)
@@ -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
-
index fc76d96..1336f3f 100644 (file)
@@ -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
index 80e5012..f4da48e 100644 (file)
@@ -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 (file)
index 0000000..ba3366d
--- /dev/null
@@ -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 <tinyara/irq.h>
+
+
+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
+}
index 1730640..6f010fa 100644 (file)
@@ -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
index 525471b..b084f61 100644 (file)
@@ -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
index f973b79..bb8a7c0 100644 (file)
  */
 
 #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
index b2aa783..7241dbf 100644 (file)
 
 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
index 440238a..483b239 100644 (file)
@@ -66,6 +66,9 @@
 /****************************************************************************
  * Definitions
  ****************************************************************************/
+#ifdef CONFIG_DEBUG_IRQ_INFO
+#define MAX_IRQNAME_SIZE 31
+#endif
 
 /****************************************************************************
  * Public Type Declarations
 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];
index ea6f46f..587fa27 100644 (file)
  *
  ****************************************************************************/
 
+#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;
        }
index db2eec6..e312578 100644 (file)
@@ -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 (file)
index 0000000..5533412
--- /dev/null
@@ -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 <stdio.h>
+#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);
+               }
+       }
+}
index fed3a14..75a6e88 100644 (file)
@@ -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;
        }
 }