You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by li...@apache.org on 2020/09/03 02:20:58 UTC
[incubator-nuttx] 02/02: arch/sim: Model host signal as NuttX's
interrupt
This is an automated email from the ASF dual-hosted git repository.
liuhaitao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 5107104bbead8179253240713a9f16d1775444ba
Author: Xiang Xiao <xi...@xiaomi.com>
AuthorDate: Sat Aug 29 14:06:56 2020 +0800
arch/sim: Model host signal as NuttX's interrupt
Signed-off-by: Xiang Xiao <xi...@xiaomi.com>
---
arch/Kconfig | 1 -
arch/sim/include/irq.h | 4 +-
arch/sim/src/sim/up_hostirq.c | 71 ++++++++++++++++++++++++++++++++++
arch/sim/src/sim/up_internal.h | 24 ++++++++++++
arch/sim/src/sim/up_interruptcontext.c | 36 ++++++++++++++++-
5 files changed, 130 insertions(+), 6 deletions(-)
diff --git a/arch/Kconfig b/arch/Kconfig
index 79b7e51..93a50ef 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -72,7 +72,6 @@ config ARCH_SIM
select ARCH_HAVE_TICKLESS
select ARCH_HAVE_POWEROFF
select ARCH_HAVE_TESTSET
- select ARCH_NOINTC
select ALARM_ARCH
select ONESHOT
select SERIAL_CONSOLE
diff --git a/arch/sim/include/irq.h b/arch/sim/include/irq.h
index 808266b..bec1d78 100644
--- a/arch/sim/include/irq.h
+++ b/arch/sim/include/irq.h
@@ -44,9 +44,7 @@
* Pre-processor Definitions
****************************************************************************/
-/* No interrupts */
-
-#define NR_IRQS 0
+#define NR_IRQS 64
/* Number of registers saved in context switch */
diff --git a/arch/sim/src/sim/up_hostirq.c b/arch/sim/src/sim/up_hostirq.c
index 9acbd59..b929620 100644
--- a/arch/sim/src/sim/up_hostirq.c
+++ b/arch/sim/src/sim/up_hostirq.c
@@ -25,6 +25,19 @@
#include <signal.h>
#include <stddef.h>
#include <stdint.h>
+#include <string.h>
+
+#include "up_internal.h"
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifdef CONFIG_SMP
+volatile void *g_current_regs[CONFIG_SMP_NCPUS];
+#else
+volatile void *g_current_regs[1];
+#endif
/****************************************************************************
* Private Types
@@ -37,6 +50,19 @@ union sigset_u
};
/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_handle_irq
+ ****************************************************************************/
+
+static void up_handle_irq(int irq, siginfo_t *info, void *context)
+{
+ up_doirq(irq, context);
+}
+
+/****************************************************************************
* Public Functions
****************************************************************************/
@@ -86,3 +112,48 @@ void up_irq_restore(uint64_t flags)
void up_irqinitialize(void)
{
}
+
+/****************************************************************************
+ * Name: up_enable_irq
+ *
+ * Description:
+ * Enable the IRQ specified by 'irq'
+ *
+ ****************************************************************************/
+
+void up_enable_irq(int irq)
+{
+ struct sigaction act;
+ sigset_t set;
+
+ /* Register signal handler */
+
+ memset(&act, 0, sizeof(act));
+ act.sa_sigaction = up_handle_irq;
+ act.sa_flags = SA_SIGINFO;
+ sigfillset(&act.sa_mask);
+ sigaction(irq, &act, NULL);
+
+ /* Unmask the signal */
+
+ sigemptyset(&set);
+ sigaddset(&set, irq);
+ pthread_sigmask(SIG_UNBLOCK, &set, NULL);
+}
+
+/****************************************************************************
+ * Name: up_disable_irq
+ *
+ * Description:
+ * Disable the IRQ specified by 'irq'
+ *
+ ****************************************************************************/
+
+void up_disable_irq(int irq)
+{
+ /* Since it's hard to mask the signal on all threads,
+ * let's change the signal handler to ignore instead.
+ */
+
+ signal(irq, SIG_IGN);
+}
diff --git a/arch/sim/src/sim/up_internal.h b/arch/sim/src/sim/up_internal.h
index 26e3f51..df24178 100644
--- a/arch/sim/src/sim/up_internal.h
+++ b/arch/sim/src/sim/up_internal.h
@@ -169,6 +169,28 @@ struct ioexpander_dev_s;
* Public Data
****************************************************************************/
+/* g_current_regs[] holds a references to the current interrupt level
+ * register storage structure. If is non-NULL only during interrupt
+ * processing. Access to g_current_regs[] must be through the macro
+ * CURRENT_REGS for portability.
+ */
+
+#ifdef CONFIG_SMP
+/* For the case of architectures with multiple CPUs, then there must be one
+ * such value for each processor that can receive an interrupt.
+ */
+
+int up_cpu_index(void); /* See include/nuttx/arch.h */
+extern volatile void *g_current_regs[CONFIG_SMP_NCPUS];
+# define CURRENT_REGS (g_current_regs[up_cpu_index()])
+
+#else
+
+extern volatile void *g_current_regs[1];
+# define CURRENT_REGS (g_current_regs[0])
+
+#endif
+
#ifdef CONFIG_SMP
/* These spinlocks are used in the SMP configuration in order to implement
* up_cpu_pause(). The protocol for CPUn to pause CPUm is as follows
@@ -192,6 +214,8 @@ extern volatile uint8_t g_cpu_paused[CONFIG_SMP_NCPUS];
* Public Function Prototypes
****************************************************************************/
+void *up_doirq(int irq, void *regs);
+
/* up_setjmp32.S ************************************************************/
int up_setjmp(void *jb);
diff --git a/arch/sim/src/sim/up_interruptcontext.c b/arch/sim/src/sim/up_interruptcontext.c
index 91661ac..7a3a9e4 100644
--- a/arch/sim/src/sim/up_interruptcontext.c
+++ b/arch/sim/src/sim/up_interruptcontext.c
@@ -41,6 +41,7 @@
#include <stdbool.h>
#include <nuttx/arch.h>
+
#include "up_internal.h"
/****************************************************************************
@@ -58,7 +59,38 @@
bool up_interrupt_context(void)
{
- /* The simulation is never in the interrupt state */
+ return CURRENT_REGS != NULL;
+}
+
+/****************************************************************************
+ * Name: up_doirq
+ ****************************************************************************/
+
+void *up_doirq(int irq, void *regs)
+{
+ /* Current regs non-zero indicates that we are processing an interrupt;
+ * CURRENT_REGS is also used to manage interrupt level context switches.
+ */
+
+ CURRENT_REGS = regs;
+
+ /* Deliver the IRQ */
+
+ irq_dispatch(irq, regs);
+
+ /* If a context switch occurred while processing the interrupt then
+ * CURRENT_REGS may have change value. If we return any value different
+ * from the input regs, then the lower level will know that a context
+ * switch occurred during interrupt processing.
+ */
+
+ regs = (void *)CURRENT_REGS;
+
+ /* Restore the previous value of CURRENT_REGS. NULL would indicate that
+ * we are no longer in an interrupt handler. It will be non-NULL if we
+ * are returning from a nested interrupt.
+ */
- return false;
+ CURRENT_REGS = NULL;
+ return regs;
}