Implements support for smaller interrupt tables as described at http://www.nuttx.org/doku.php?id=wiki:howtos:smallvectors . This is largely the work of Mark Schulte. However, I have made several changes to match with the Wiki document. If you like the change, thanks go to Marc. For any errors you can blame me.
This commit is contained in:
parent
eca7ae3043
commit
c2b620b4f8
38
arch/Kconfig
38
arch/Kconfig
@ -621,6 +621,44 @@ config ARCH_RAMVECTORS
|
||||
If ARCH_RAMVECTORS is defined, then the architecture will support
|
||||
modifiable vectors in a RAM-based vector table.
|
||||
|
||||
config ARCH_MINIMAL_VECTORTABLE
|
||||
bool "Minimal RAM usage for vector table"
|
||||
default n
|
||||
---help---
|
||||
Use a minimum amount of RAM for the vector table.
|
||||
|
||||
Instead of allowing irq_attach() to work for all interrupt vectors,
|
||||
restrict to only working for a select few (defined in your board
|
||||
configuration). This can dramatically reduce the amount of RAM used
|
||||
be your vector table.
|
||||
|
||||
To use this setting, you must have a file in your board config that
|
||||
provides:
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
const irq_t g_irqmap[NR_IRQS] =
|
||||
{
|
||||
... IRQ to index mapping values ...
|
||||
};
|
||||
|
||||
This table is index by the hardware IRQ number and provides a value
|
||||
in the range of 0 to CONFIG_ARCH_NUSER_INTERRUPTS that the new,
|
||||
mapped index into the vector table. Unused, unmapped interrupts
|
||||
should be set to (irq_t)-1. So, for example, if g_irqmap[37] == 24,
|
||||
Then the hardware interrupt vector 37 will be mapped to the interrupt
|
||||
vector table at index 24. if g_irqmap[42] == (irq_t)-1, then hardware
|
||||
interrupt vector 42 is not used and if it occurs will result in an
|
||||
unexpected interrupt crash.
|
||||
|
||||
config ARCH_NUSER_INTERRUPTS
|
||||
int "Number of interrupts"
|
||||
default 0
|
||||
depends on ARCH_MINIMAL_VECTORTABLE
|
||||
---help---
|
||||
If CONFIG_ARCH_MINIMAL_VECTORTABLE is defined, then this setting
|
||||
defines the actual number of valid, mapped interrupts in g_irqmap.
|
||||
This number will be the new size of the OS vector table
|
||||
|
||||
comment "Board Settings"
|
||||
|
||||
config BOARD_LOOPSPERMSEC
|
||||
|
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* include/nuttx/arch.h
|
||||
*
|
||||
* Copyright (C) 2007-2016 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* include/nuttx/irq.h
|
||||
*
|
||||
* Copyright (C) 2007-2011, 2013, 2016 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2011, 2013, 2016-2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -43,6 +43,7 @@
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
# include <stdint.h>
|
||||
# include <assert.h>
|
||||
# include <arch/irq.h>
|
||||
#endif
|
||||
@ -50,6 +51,7 @@
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* IRQ detach is a convenience definition. Detaching an interrupt handler
|
||||
* is equivalent to setting a NULL interrupt handler.
|
||||
*/
|
||||
@ -62,9 +64,19 @@
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/* This struct defines the way the registers are stored */
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
/* This type is an integer type large enough to hold the largest IRQ number. */
|
||||
|
||||
#if NR_IRQS <= 256
|
||||
typedef uint8_t irq_t;
|
||||
#elif NR_IRQS <= 65536
|
||||
typedef uint16_t irq_t;
|
||||
#else
|
||||
typedef uint32_t irq_t;
|
||||
#endif
|
||||
|
||||
/* This struct defines the form of an interrupt service routine */
|
||||
|
||||
typedef int (*xcpt_t)(int irq, FAR void *context, FAR void *arg);
|
||||
#endif
|
||||
|
||||
|
@ -51,7 +51,16 @@
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_ARCH_MINIMAL_VECTORTABLE) && \
|
||||
!defined(CONFIG_ARCH_NUSER_INTERRUPTS)
|
||||
# error CONFIG_ARCH_NUSER_INTERRUPTS is not defined
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/* This is the type of the list of interrupt handlers, one for each IRQ.
|
||||
@ -60,7 +69,7 @@
|
||||
* interrupt.
|
||||
*/
|
||||
|
||||
struct irq
|
||||
struct irq_info_s
|
||||
{
|
||||
xcpt_t handler; /* Address of the interrupt handler */
|
||||
FAR void *arg; /* The argument provided to the interrupt handler. */
|
||||
@ -75,7 +84,17 @@ struct irq
|
||||
* occurrence of an interrupt.
|
||||
*/
|
||||
|
||||
extern struct irq g_irqvector[NR_IRQS];
|
||||
#ifdef CONFIG_ARCH_MINIMAL_VECTORTABLE
|
||||
extern struct irq_info_s g_irqvector[CONFIG_ARCH_NUSER_INTERRUPTS];
|
||||
#else
|
||||
extern struct irq_info_s g_irqvector[NR_IRQS];
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_MINIMAL_VECTORTABLE
|
||||
/* This is the interrupt vector mapping table */
|
||||
|
||||
extern const irq_t g_irqmap[NR_IRQS];
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* This is the spinlock that enforces critical sections when interrupts are
|
||||
|
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* sched/irq/irq_attach.c
|
||||
*
|
||||
* Copyright (C) 2007-2008, 2010, 2012 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2008, 2010, 2012, 2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -64,6 +64,21 @@ int irq_attach(int irq, xcpt_t isr, FAR void *arg)
|
||||
if ((unsigned)irq < NR_IRQS)
|
||||
{
|
||||
irqstate_t flags;
|
||||
int ndx;
|
||||
|
||||
#ifdef CONFIG_ARCH_MINIMAL_VECTORTABLE
|
||||
/* Is there a mapping for this IRQ number? */
|
||||
|
||||
ndx = g_irqmap[irq];
|
||||
if ((unsigned)ndx >= CONFIG_ARCH_NUSER_INTERRUPTS)
|
||||
{
|
||||
/* No.. then return failure. */
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
ndx = irq;
|
||||
#endif
|
||||
|
||||
/* If the new ISR is NULL, then the ISR is being detached.
|
||||
* In this case, disable the ISR and direct any interrupts
|
||||
@ -94,10 +109,11 @@ int irq_attach(int irq, xcpt_t isr, FAR void *arg)
|
||||
arg = NULL;
|
||||
}
|
||||
|
||||
/* Save the new ISR in the table. */
|
||||
/* Save the new ISR and its argument in the table. */
|
||||
|
||||
g_irqvector[ndx].handler = isr;
|
||||
g_irqvector[ndx].arg = arg;
|
||||
|
||||
g_irqvector[irq].handler = isr;
|
||||
g_irqvector[irq].arg = arg;
|
||||
leave_critical_section(flags);
|
||||
ret = OK;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* sched/irq/irq_dispatch.c
|
||||
*
|
||||
* Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007, 2008, 2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -67,18 +67,34 @@ void irq_dispatch(int irq, FAR void *context)
|
||||
/* Perform some sanity checks */
|
||||
|
||||
#if NR_IRQS > 0
|
||||
if ((unsigned)irq >= NR_IRQS || g_irqvector[irq].handler == NULL)
|
||||
if ((unsigned)irq >= NR_IRQS)
|
||||
{
|
||||
vector = irq_unexpected_isr;
|
||||
arg = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
vector = g_irqvector[irq].handler;
|
||||
arg = g_irqvector[irq].arg;
|
||||
#ifdef CONFIG_ARCH_MINIMAL_VECTORTABLE
|
||||
int ndx = g_irqmap[irq];
|
||||
if ((unsigned)ndx >= CONFIG_ARCH_NUSER_INTERRUPTS)
|
||||
{
|
||||
vector = irq_unexpected_isr;
|
||||
arg = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
vector = g_irqvector[ndx].handler;
|
||||
arg = g_irqvector[ndx].arg;
|
||||
}
|
||||
#else
|
||||
vector = g_irqvector[irq].handler;
|
||||
arg = g_irqvector[irq].arg;
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
vector = irq_unexpected_isr;
|
||||
arg = NULL;
|
||||
#endif
|
||||
|
||||
/* Then dispatch to the interrupt handler */
|
||||
|
@ -43,11 +43,29 @@
|
||||
|
||||
#include "irq/irq.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* This is the number of entries in the interrupt vector table */
|
||||
|
||||
#ifdef CONFIG_ARCH_MINIMAL_VECTORTABLE
|
||||
# define TAB_SIZE CONFIG_ARCH_NUSER_INTERRUPTS
|
||||
#else
|
||||
# define TAB_SIZE NR_IRQS
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
struct irq g_irqvector[NR_IRQS];
|
||||
/* This is the interrupt vector table */
|
||||
|
||||
#ifdef CONFIG_ARCH_MINIMAL_VECTORTABLE
|
||||
struct irq_info_s g_irqvector[CONFIG_ARCH_NUSER_INTERRUPTS];
|
||||
#else
|
||||
struct irq_info_s g_irqvector[NR_IRQS];
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@ -67,7 +85,7 @@ void irq_initialize(void)
|
||||
|
||||
/* Point all interrupt vectors to the unexpected interrupt */
|
||||
|
||||
for (i = 0; i < NR_IRQS; i++)
|
||||
for (i = 0; i < TAB_SIZE; i++)
|
||||
{
|
||||
g_irqvector[i].handler = irq_unexpected_isr;
|
||||
g_irqvector[i].arg = NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user