Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

One

...

of

...

the

...

largest

...

OS

...

data

...

structures

...

is

...

the

...

vector

...

table,

...

g_irqvector

...

[]

...

.

...

This

...

is

...

the

...

table

...

that

...

holds

...

the

...

vector

...

information

...

when

...

irq_attach()

...

is

...

called

...

and

...

used

...

to

...

dispatch

...

interrupts

...

by

...

irq_dispatch()

...

.

...

Recent

...

changes

...

have

...

made

...

that

...

table

...

even

...

larger,

...

for

...

32-bit

...

arm

...

the

...

size

...

of

...

that

...

table

...

is

...

given

...

by:

Code Block
  nbytes = number_of_interrupts * (2 * sizeof(void *))

...

For a 32-bit ARM like the STM32 with, say, 100 interrupt vectors, this size would be 800 bytes of memory. That is not a lot for high-end MCUs with a lot of RAM memory, but could be a show stopper for MCUs with minimal RAM.

...

Two

...

approaches

...

for

...

reducing

...

the

...

size

...

of

...

the

...

vector

...

tables

...

are

...

described

...

below.

...

Both

...

depend

...

on

...

the

...

fact

...

that

...

not

...

all

...

interrupts

...

are

...

used

...

on

...

a

...

given

...

MCU.

...

Most

...

of

...

the

...

time,

...

the

...

majority

...

of

...

entries

...

in

...

g_irqvector

...

[]

...

are

...

zero

...

because

...

only

...

a

...

small

...

number

...

of

...

interrupts

...

are

...

actually

...

attached

...

and

...

enabled

...

by

...

the

...

application.

...

If

...

you

...

know

...

that

...

certain

...

IRQ

...

numbers

...

are

...

not

...

going

...

to

...

be

...

used,

...

then

...

it

...

is

...

possible

...

to

...

filter

...

those

...

out

...

and

...

reduce

...

the

...

size

...

to

...

the

...

number

...

of

...

supported

...

interrupts.

For example, if the actual number of interrupts used were 20, the the above requirement would go from 800 bytes to 160 bytes.

Software IRQ Remapping

...

...

[On

...

March

...

3,

...

2017,

...

support

...

for

...

this

...

"Software

...

IRQ

...

Remapping"

...

as

...

included

...

in

...

the

...

NuttX

...

repository.]

...

One

...

of

...

the

...

simplest

...

way

...

of

...

reducing

...

the

...

size

...

of

...

g_irqvector

...

[

...

]

...

would

...

be

...

to

...

remap

...

the

...

large

...

set

...

of

...

physcial

...

interrupt

...

vectors

...

into

...

a

...

much

...

small

...

set

...

of

...

interrupts

...

that

...

are

...

actually

...

used.

...

For

...

the

...

sake

...

of

...

discussion,

...

let's

...

imagine

...

two

...

new

...

configuration

...

settings:

  • CONFIG_ARCH_MINIMAL_VECTORTABLE: Enables IRQ mapping
  • CONFIG_ARCH_NUSER_INTERRUPTS: The number of IRQs after mapping.

...

unmigrated-wiki-markup
Code Block
  #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

The

...

g_irqvector

...

[]

...

table

...

is

...

accessed

...

in

...

only

...

three

...

places:

irq_attach()

irq_attach() receives the physical vector number along with the information needed later to dispatch interrupts:

...

unmigrated-wiki-markup
Code Block
  #ifdef CONFIG_ARCH_MINIMAL_VECTORTABLE
  int ndx = g_irqmap[irq];
  #else
  int ndx = irq;
  #endif

where

...

up_mapirq

...

[]

...

is

...

an

...

array

...

indexed

...

by

...

the

...

physical

...

interrupt

...

vector

...

number

...

and

...

contains

...

the

...

new,

...

mapped

...

interrupt

...

vector

...

table

...

index.

...

This

...

array

...

must

...

be

...

provided

...

by

...

platform-specific

...

code.

...

...

irq_attach()

...

would

...

this

...

use

...

this

...

index

...

to

...

set

...

the

...

g_irqvector

...

[].

Code Block
  g_irqvector[ndx].handler = isr;
  g_irqvector[ndx].arg     = arg;

...

Code Block
  vector = g_irqvector[ndx].handler;
  arg    = g_irqvector[ndx].arg;
Code Block
  vector(irq, context, arg);


irq_initialize()

...

...

irq_initialize()

...

:

...

simply

...

set

...

the

...

g_irqvector

...

[]

...

table

...

a

...

known

...

state

...

on

...

power-up.

...

It

...

would

...

only

...

have

...

to

...

distinquish

...

the

...

difference

...

in

...

sizes.

unmigrated-wiki-markup
Code Block
  #ifdef CONFIG_ARCH_MINIMAL_VECTORTABLE
  #  define TAB_SIZE CONFIG_ARCH_NUSER_INTERRUPTS
  #else
  #  define TAB_SIZE NR_IRQS
  #endif
Code Block
  for (i = 0; i < TAB_SIZE; i++)

g_mapirq

...

[]

...

An implementation of up_mapirq() might be something like:

{{g
Code Block
  #include <nuttx/irq.h>
Code Block
  const irq_mapped_t g_irqmap[NR_IRQS] =
  {
    ... IRQ to index mapping values ...
  };
Wiki Markup

g_irqmap

...

[]

...

is

...

a

...

array

...

of

...

mapped

...

irq

...

table

...

indices.

...

It

...

contains

...

the

...

mapped

...

index

...

value

...

and

...

is

...

itself

...

indexed

...

by

...

the

...

physical

...

interrupt

...

vector

...

number.

...

It

...

provides

...

an

...

irq_mapped_t

...

value

...

in

...

the

...

range

...

of

...

0

...

to

...

CONFIG_ARCH_NUSER_INTERRUPTS

...

that

...

is

...

the

...

new,

...

mapped

...

index

...

into

...

the

...

vector

...

table.

...

Unsupported

...

IRQs

...

would

...

simply

...

map

...

to

...

an

...

out

...

of

...

range

...

value

...

like

...

IRQMAPPED_MAX

...

.

...

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] == IRQMAPPED_MAX, then hardware interrupt vector 42 is not used and if it occurs will result in an unexpected interrupt crash.

Hardware Vector Remapping

...

...

[This

...

technical

...

approach

...

is

...

discussed

...

here

...

but

...

is

...

discouraged

...

because

...

of

...

technical

...

"Complications"

...

and

...

"Dubious

...

Performance

...

Improvements"

...

discussed

...

at

...

the

...

end

...

of

...

this

...

section.]

...

Most ARMv7-M architectures support two mechanism for handling interrupts:

...

The first time that xyz_vector.h included, it defines the hardware vector table. The hardware vector table consists of NR_IRQS 32-bit addresses in an array. This is accomplished by setting:

Code Block
  #undef VECTOR
  #define VECTOR(l,i) .word l
Code Block
  #undef UNUSED
  #define UNUSED(i)   .word stm32_reserved

...

These are the valus of UNUSED and VECTOR macros on the second time the xzy_vector.h is included by stm32_vectors.S:

Code Block

  .macro HANDLER, label, irqno
      .thumb_func
  \label:
      mov r0, #\irqno
      b       exception_common
  .endm
Code Block
  #undef VECTOR
  #define VECTOR(l,i) HANDLER l, i
Code Block
  #undef UNUSED
  #define UNUSED(i)


In the above USART1 example, a single handler would be generated that will provide the IRQ number 12. Remember that 12 is the expansion of the macro STM32_IRQ_USART1 that is provided in the arch/arm/include/stm32/xyz_irq.h header file:

...

unmigrated-wiki-markup
Code Block
  ...
  VECTOR(stm32_usart1, STM32_IRQ_USART1 << 8 | STM32_INDEX_USART1)
  UNUSED(0)
  UNUSED(0)
  ...

The

...

STM32_INDEX_USART1

...

would

...

have

...

the

...

value

...

12

...

and

...

STM32_IRQ_USART1

...

would

...

be

...

as

...

before

...

(53).

...

This

...

encoded

...

value

...

would

...

be

...

received

...

by

...

irq_dispatch()

...

and

...

it

...

would

...

decode

...

both

...

the

...

index

...

and

...

the

...

physical

...

vector

...

number.

...

It

...

would

...

use

...

the

...

index

...

to

...

look

...

up

...

in

...

the

...

g_irqvector

...

[]

...

table

...

but

...

would

...

pass

...

the

...

physical

...

vector

...

number

...

to

...

the

...

interrupt

...

handler

...

as

...

the

...

IRQ

...

number.

A lookup would still be required in irq_attach() in order to convert the physical vector number back to an index (100 uint8_t entries in our example). So some lookup is unavoidable.

...