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:
Gregory Nutt 2017-03-03 08:55:16 -06:00
parent eca7ae3043
commit c2b620b4f8
7 changed files with 134 additions and 15 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;