Skip to content
Mike Schwager edited this page Oct 6, 2015 · 5 revisions

Table of Contents

Saving Memory

In order to make the Enable Interrupt library work as it does and easy to use, some compromises were necessary regarding code size. For example, on the ATmega328 an array of function pointers is defined for each port:

        functionPointersPortB portBFunctions = { NULL, NULL, NULL, NULL, NULL, NULL, };

This sets up a block of memory 6 * 2-bytes long- 12 bytes total. Similarly for port C (12 bytes), port D (16 bytes), and an array of 4 bytes (2 function pointers) for the two External interrupts: 44 bytes total.

If you need a single interrupt on a Port B pin, that's only 2 bytes (a single function pointer) required, and 42 bytes wasted, or 2% of your available static RAM. So the library has included some features to allow you to shut off unneeded variables and functions.

Additionally you may find that this library conficts with other libraries (the SoftSerial library is a case in point). You may find that disabling one or more ISRs in this library enables you to use it with a conflicting library.

Howto

  • Refer to the Usage#PIN / PORT BESTIARY section for the relationships between Arduino pins and the ATmega ports.
  • Inventory your interrupt pins, and decide which ports you are able to shut off.
  • In your main sketch, precede the #include <EnableInterrupt.h> with #define statements that will prevent the variables and functions associated with the chosen ports from compiling, by inserting #define EI_NOTPORTx where x refers to the port letter you wish to eliminate.
  • For external interrupts, #define EI_INTx to prevent code from compiling for your chosen External interrupt pins, where x refers to the External interrupt number.
  • You can also #define EI_NOTEXTERNAL if you are not using any External interrupts.
  • You can #define EI_NOTPINCHANGE if you are not using any Pin Change interrupts.
See the example below.

Example

I have pin 7 and pin 8 each connected to a pushbutton switch on an Arduino Uno. Referring to the Bestiary, I see that these pins are on 2 ports:

Arduino
Pin     Port

7       PD7
8       PB0

This means I don't need to compile any code for Port C. Nor am I using External Interrupts. Therefore, my sketch can begin as follows:

#define EI_NOTPORTC
#define EI_NOTEXTERNAL
#include <EnableInterrupt.h>

Note that I am using only 1 interrupt pin on each port. If possible, it would be better to put the 2 pins on a single port. For example, move pin 8 to use pin 6 instead. Thus we would only be using port D, and we could define EI_NOTPORTB as well, and save another few bytes.

Directives List

These are the compiler directives available to you for the various processors. Check the Usage page to see which pins correspond to the

INTx
and
PORTx
designations:

ATmega328

Arduino Uno, etc.

EI_NOTEXTERNAL  EI_NOTINT0  EI_NOTINT1

EI_NOTPINCHANGE EI_NOTPORTB EI_NOTPORTC EI_NOTPORTD

ATmega2560

Arduino Mega, etc.

EI_NOTEXTERNAL  EI_NOTINT0  EI_NOTINT1  EI_NOTINT2  EI_NOTINT3  EI_NOTINT4
EI_NOTINT5      EI_NOTINT6  EI_NOTINT7

EI_NOTPINCHANGE EI_NOTPORTB EI_NOTPORTJ EI_NOTPORTK

ATmega32u4

Arduino Leonardo, etc.

EI_NOTEXTERNAL  EI_NOTINT0  EI_NOTINT1  EI_NOTINT2  EI_NOTINT3  EI_NOTINT6

EI_NOTPINCHANGE EI_NOTPORTB

ATmega644/1284

EI_NOTEXTERNAL  EI_NOTINT0  EI_NOTINT1  EI_NOTINT2

EI_NOTPINCHANGE EI_NOTPORTA EI_NOTPORTB EI_NOTPORTC EI_NOTPORTD

ATtiny 44/84

EI_NOTEXTERNAL EI_NOTINT0

EI_NOTPINCHANGE EI_NOTPORTA EI_NOTPORTB

ATtiny 45/85

EI_NOTEXTERNAL EI_NOTINT0

EI_NOTPINCHANGE EI_NOTPORTB

Arduino Due

Not Applicable.

HowMuch

Here are some tests to demonstrate the amount of space saved by these optimizations. The Simple.ino example sketch was used with ARDUINOPIN defined as pin 10, and the code was compiled for the ATmega2560. Note that pin 10 is on Port B:

Compile Simple.ino, no memory saving features enabled:
Program:    6402 bytes (2.4% Full)
(.text + .data + .bootloader)

Data:        859 bytes (10.5% Full)
(.data + .bss + .noinit)


Compile Simple.ino, using pin 10, define EI_NOTEXTERNAL:
Program:    5328 bytes (2.0% Full)
(.text + .data + .bootloader)

Data:        843 bytes (10.3% Full)
(.data + .bss + .noinit)

Compile Simple.ino, using pin 10, define EI_NOTPORTJ:
Program:    5006 bytes (1.9% Full)
(.text + .data + .bootloader)

Data:        825 bytes (10.1% Full)
(.data + .bss + .noinit)

Compile Simple.ino, using pin 10, define EI_NOTPORTJ EI_NOTPORTK:
Program:    4686 bytes (1.8% Full)
(.text + .data + .bootloader)

Data:        806 bytes (9.8% Full)
(.data + .bss + .noinit)


Compile Simple.ino, using pin 10, define EI_NOTPORTJ EI_NOTPORTK EI_NOTEXTERNAL:
Program:    4674 bytes (1.8% Full)
(.text + .data + .bootloader)

Data:        806 bytes (9.8% Full)
(.data + .bss + .noinit)