Added arduino libs
هذا الالتزام موجود في:
929
libraries/EnableInterrupt/Technical_Notes
Normal file
929
libraries/EnableInterrupt/Technical_Notes
Normal file
@@ -0,0 +1,929 @@
|
||||
// in vim, :set ts=2 sts=2 sw=2 et
|
||||
|
||||
// Enable Interrupts
|
||||
|
||||
=====================================================================================================
|
||||
=====================================================================================================
|
||||
ATmega328 Support
|
||||
=====================================================================================================
|
||||
=====================================================================================================
|
||||
|
||||
Interrupt pins:
|
||||
Pin External Pin Pin Change Pin Pin Change
|
||||
Interrupt Interrupt Interrupt
|
||||
3 INT1 PD3 0 PCINT16 PD0 A0 PCINT8 PC0
|
||||
2 INT0 PD2 1 PCINT17 PD1 A1 PCINT9 PC1
|
||||
2 PCINT18 PD2 A2 PCINT10 PC2
|
||||
3 PCINT19 PD3 A3 PCINT11 PC3
|
||||
4 PCINT20 PD4 A4 PCINT12 PC4
|
||||
5 PCINT21 PD5 A5 PCINT13 PC5
|
||||
6 PCINT22 PD6
|
||||
7 PCINT23 PD7
|
||||
8 PCINT0 PB0
|
||||
9 PCINT1 PB1
|
||||
10 PCINT2 PB2
|
||||
11 PCINT3 PB3
|
||||
12 PCINT4 PB4
|
||||
13 PCINT5 PB5
|
||||
|
||||
// The External Interrupts are triggered by the INT0 and INT1 pins or any of the PCINT23...0 pins.
|
||||
|
||||
// PIN CHANGE INTERRUPT REGISTER BESTIARY
|
||||
// ATmega328p and similar (328, 168)
|
||||
The pin change interrupt PCI2 will trigger if any enabled PCINT[23:16] pin toggles.
|
||||
The pin change interrupt PCI1 will trigger if any enabled PCINT[14:8] pin toggles.
|
||||
The pin change interrupt PCI0 will trigger if any enabled PCINT[7:0] pin toggles.
|
||||
The PCMSK2, PCMSK1 and PCMSK0 Registers control which pins contribute to the pin change interrupts.
|
||||
Pin change interrupts on PCINT23...0 are detected asynchronously. This implies that these interrupts
|
||||
can be used for waking the part also from sleep modes other than Idle mode.
|
||||
|
||||
// GLOBALLY
|
||||
SREG: 7 6 5 4 3 2 1 0 (AVR Status Register)
|
||||
I -Global Interrupt Enable bit Set to enable interrupts.
|
||||
rw
|
||||
|
||||
// PIN CHANGE INTERRUPTS REGISTER BESTIARY
|
||||
PCICR: 7 6 5 4 3 2 1 0 (When PCIE2 is set and GIE is set, PCI2 is enabled)
|
||||
PCIE2 1 0 Likewise for 1 and 0.
|
||||
- - - - - rw rw rw
|
||||
|
||||
PCMSK2:7 6 5 4 3 2 1 0 (Selects whether pin change interrupt is enabled on PCINT23:16
|
||||
PCINT23 ... PCINT16 If PCIE2 in PCICR and this bit is set, it is enabled on that
|
||||
rw rw rw rw rw rw rw rw pin.)
|
||||
PD7 PD6 PD5 PD4 PD3 PD2 PD1 PD0 =PORTD
|
||||
|
||||
PCMSK1:7 6 5 4 3 2 1 0 (Selects whether pin change interrupt is enabled on PCINT14:8
|
||||
- PCINT14 ... PCINT8 If PCIE1 in PCICR and this bit is set, it is enabled on that
|
||||
r rw rw rw rw rw rw rw pin.)
|
||||
PC6 PC5 PC4 PC3 PC2 PC1 PC0 =PORTC
|
||||
|
||||
PCMSK0:7 6 5 4 3 2 1 0 (Selects whether pin change interrupt is enabled on PCINT7:0
|
||||
PCINT7 ... PCINT0 If PCIE0 in PCICR and this bit is set, it is enabled on that
|
||||
rw rw rw rw rw rw rw rw pin.)
|
||||
PB7 PB6 PB5 PB4 PB3 PB2 PB1 PB0 =PORTB
|
||||
|
||||
// set...
|
||||
PCIFR: 7 6 5 4 3 2 1 0 (When logic change triggers IRQ, bececomes set. Cleared when
|
||||
PCIF2 1 0 IRQ is executed. PCIF2 == PCIE2, etc.)
|
||||
- - - - - rw rw rw
|
||||
|
||||
// EXTERNAL INTERRUPTS REGISTER BESTIARY
|
||||
For ATmega328p and the like.
|
||||
|
||||
INT0=pin2, INT1=pin3
|
||||
|
||||
EICRA: 7 6 5 4 3 2 1 0 (External Interrupt Control Register A)
|
||||
ISC 11 10 01 00 Interrupt Sense Control Bits
|
||||
- - - - rw rw rw rw
|
||||
|
||||
ISC11 / ISC10 : INT1 ISC01 / ISC00
|
||||
0 0 Low (similar to ISC11/10)
|
||||
0 1 Change
|
||||
1 0 Falling
|
||||
1 1 Rising
|
||||
|
||||
EIMSK: 7 6 5 4 3 2 1 0 (External Interrupt Mask Register)
|
||||
INT1 INT0
|
||||
- - - - - - rw rw set to 1 to enable this interrupt
|
||||
|
||||
// set...
|
||||
EIFR: INTF1: Bit 1: set when edge/logic chg on INT1 triggers IRQ. Cleared when IRQ executed.
|
||||
INTF0: Bit 0: set when edge/logic chg on INT0 triggers IRQ. Cleared when IRQ executed.
|
||||
|
||||
|
||||
The INT0 and INT1 interrupts can be triggered by a falling or rising edge or a low level. This is
|
||||
set up as indicated in the specification for the External Interrupt Control Register A – EICRA.
|
||||
When the INT0 or INT1 interrupts are enabled and are configured as level triggered, the inter-
|
||||
rupts will trigger as long as the pin is held low.
|
||||
Low level interrupt on INT0 and INT1 is detected asynchronously. This implies that this interrupt
|
||||
can be used for waking the part also from sleep modes other than Idle mode. The I/O clock is halted
|
||||
in all sleep modes except Idle mode.
|
||||
|
||||
=============================================================================================
|
||||
|
||||
Fri Jan 23 21:51:01 CST 2015
|
||||
PROBLEM:
|
||||
I have a "dirty" switch: it bounces a lot when pressed. The bounces can occur on the order of
|
||||
microseconds apart. So pretend I have turned on a port as an input port, and the pullup resistor
|
||||
is on. I have enabled a Pin Change Interrupt on the pin. It will trigger on any level change.
|
||||
So when I press the switch, the signal goes from high to low and the interrupt is triggered.
|
||||
|
||||
Notice that for Pin Change Interrupts, the interrupt can take place when any pin on the port is
|
||||
interrupted. If you have the luxury of knowing ahead of time which pin(s) are interrupting, you
|
||||
can design fast, custom code that will react to your simple situation. But remember that I am
|
||||
writing a library: I don't know which pin may be doing the interrupting. So I have to survey the
|
||||
pins to figure out which one(s) changed, and had triggered the interrupt. Furthermore, there is
|
||||
an appreciable amount of time that it takes from the moment the triggering event happened to
|
||||
when I enter the interrupt subroutine (ISR) and have gone through the logic to figure out which
|
||||
pins did the triggering. ...How much time? That I aim to find out.
|
||||
|
||||
Why is this a big deal? Remember my bouncy switch? ...The interrupt triggers, the ISR starts up,
|
||||
and the first thing I need to do is query the port to see the state of its pins. Well, some time
|
||||
has elapsed since the triggering event and this query. In the course of that time, it's entirely
|
||||
possible- and I'm writing this because it's not only possible, but it can happen quite readily-
|
||||
that the state of the pin changes before I get a chance to sample it. So I get an interrupt but
|
||||
it looks like a false alarm! The ISR never calls the user's function because none of the user's
|
||||
interrupt pins appear to have changed.
|
||||
|
||||
There is no complete solution to this problem, because of the nature of Pin Change Interrupts.
|
||||
All you can do is mitigate the situation. I will attempt to do so by capturing the state of the
|
||||
port as early as possible in the ISR. The question is, how early is that?
|
||||
|
||||
I attempt a test: my ISR looks like this; this will turn on and off the Arduino Uno's pin 13 LED:
|
||||
|
||||
ISR(PORTC_VECT, ISR_NAKED) {
|
||||
uint8_t interruptMask;
|
||||
uint8_t ledon, ledoff;
|
||||
|
||||
ledon=0b00100000; ledoff=0b0;
|
||||
|
||||
PORTB=ledoff; // LOW
|
||||
PORTB=ledon; // HIGH
|
||||
PORTB=ledoff; // LOW
|
||||
PORTB=ledon; // HIGH
|
||||
PORTB=ledoff; // LOW
|
||||
(...)
|
||||
}
|
||||
|
||||
The generated assembly code looks like this:
|
||||
|
||||
00000292 <__vector_4>:
|
||||
ledon=0b00100000; ledoff=0b0;
|
||||
|
||||
PORTB=ledoff; // LOW
|
||||
292: 15 b8 out 0x05, r1 ; 5
|
||||
PORTB=ledon; // HIGH
|
||||
294: 80 e2 ldi r24, 0x20 ; 32
|
||||
296: 85 b9 out 0x05, r24 ; 5
|
||||
PORTB=ledoff; // LOW
|
||||
298: 15 b8 out 0x05, r1 ; 5
|
||||
PORTB=ledon; // HIGH
|
||||
29a: 85 b9 out 0x05, r24 ; 5
|
||||
PORTB=ledoff; // LOW
|
||||
29c: 15 b8 out 0x05, r1 ; 5
|
||||
|
||||
Notice a little optimization here: r1 is defined to always contain 0, so we don't even have to load
|
||||
a value from memory. 0 is an important number! This makes the initial command very quick, and by using
|
||||
an oscilloscope we can see just how quickly the chip reacts after receiving the signal.
|
||||
see just how fast
|
||||
|
||||
|
||||
***** MACRO vs. INLINE the ISR frontend **************************
|
||||
The code compiles to very similar assembler. However, the inline is better looking C code.
|
||||
Refer to the "testing0" branch for comparison.
|
||||
|
||||
I will use the INLINE method in the production code.
|
||||
***** MACRO vs. INLINE the ISR frontend **************************
|
||||
|
||||
A lot of the basic Pin and Port definitions are in /usr/avr/include/avr/iom328p.h
|
||||
|
||||
================== ================== ================== ================== ==================
|
||||
|
||||
=====================================================================================================
|
||||
=====================================================================================================
|
||||
Leonardo Support LEONARDO
|
||||
=====================================================================================================
|
||||
=====================================================================================================
|
||||
|
||||
// Map SPI port to 'new' pins D14..D17
|
||||
static const uint8_t SS = 17;
|
||||
static const uint8_t MOSI = 16;
|
||||
static const uint8_t MISO = 14;
|
||||
static const uint8_t SCK = 15;
|
||||
// A0 starts at 18
|
||||
|
||||
|
||||
Interrupt pins:
|
||||
Pin External Pin Pin Change
|
||||
Interrupt Interrupt
|
||||
3 INT0 PD0 8 PCINT4 PB4
|
||||
2 INT1 PD1 9 PCINT5 PB5
|
||||
0 INT2 PD2 10 PCINT6 PB6
|
||||
1 INT3 PD3 11 PCINT7 PB7
|
||||
7 INT6 PE6 SCK/15 PCINT1 PB1
|
||||
MOSI/16 PCINT2 PB2
|
||||
MISO/14 PCINT3 PB3
|
||||
SS/17 PCINT0 PB0 (on 3rd party boards)
|
||||
|
||||
on ICSP:
|
||||
SCK/15: PCINT1 (PB1)
|
||||
MOSI/16: PCINT2 (PB2)
|
||||
MISO/14: PCINT3 (PB3)
|
||||
|
||||
PCINT0 (PB0) is RXLED and is not exposed as a pin on the Leonardo board.
|
||||
|
||||
External Interrupts ------------------------------------------------------------------------------
|
||||
|
||||
...it is recommended to first disable INTn by clearing its Interrupt Enable bit in the
|
||||
EIMSK Register. Then, the ISCn bit can be changed. Finally, the INTn interrupt flag should be
|
||||
cleared by writing a logical one to its Interrupt Flag bit (INTFn) in the EIFR Register before the
|
||||
interrupt is re-enabled.
|
||||
|
||||
EICRA: 7 6 5 4 3 2 1 0 (External Interrupt Control Register A)
|
||||
ISC: 31 30 21 20 11 10 01 00 Interrupt Sense Control Bits
|
||||
rw rw rw rw rw rw rw rw
|
||||
|
||||
EICRB: 7 6 5 4 3 2 1 0 (External Interrupt Control Register A)
|
||||
ISC: - - 61 60 - - - - Interrupt Sense Control Bits
|
||||
rw rw rw rw rw rw rw rw
|
||||
|
||||
ISCx1 / ISCx0 : INTx
|
||||
0 0 Low
|
||||
0 1 Change
|
||||
1 0 Falling
|
||||
1 1 Rising
|
||||
|
||||
EIMSK: 7 6 5 4 3 2 1 0 (External Interrupt Mask Register)
|
||||
n n n n n
|
||||
- rw - - rw rw rw rw set to 1 to enable this interrupt
|
||||
|
||||
n= INTn number
|
||||
|
||||
External Interrupt Flag Register is set to 1 when a signal generates an IRQ.
|
||||
Cleared upon entering the ISR. Can be cleared by writing a 1 to it.
|
||||
EIFR: 7 6 5 4 3 2 1 0 (External Interrupt Flag Register)
|
||||
n n n n n
|
||||
- rw - - rw rw rw rw
|
||||
|
||||
n= INTn number
|
||||
|
||||
|
||||
Pin Change Interrupts ---------------------------------------------------------------------------
|
||||
// PIN CHANGE INTERRUPTS REGISTER BESTIARY
|
||||
PCICR: 7 6 5 4 3 2 1 0 (When PCIE0 is set and GIE is set, PCI0 is enabled)
|
||||
PCIE0
|
||||
- - - - - - - rw
|
||||
|
||||
// set...
|
||||
PCIFR: 7 6 5 4 3 2 1 0 (When logic change triggers IRQ, bececomes set. Cleared when
|
||||
PCIF0 IRQ is executed. PCIF0 == PCIE0.)
|
||||
- - - - - - - rw Can be cleared by writing 1 to it.
|
||||
|
||||
PCMSK0:7 6 5 4 3 2 1 0 (Selects whether pin change interrupt is enabled on PCINT7:0
|
||||
PCINT7 ... PCINT0 If PCIE0 in PCICR and this bit is set, it is enabled on that
|
||||
rw rw rw rw rw rw rw rw pin.)
|
||||
PB7 PB6 PB5 PB4 PB3 PB2 PB1 PB0 =PORTB
|
||||
|
||||
=====================================================================================================
|
||||
=====================================================================================================
|
||||
ATmega2560 Support
|
||||
=====================================================================================================
|
||||
=====================================================================================================
|
||||
|
||||
External Interrupts ------------------------------------------------------------------------------
|
||||
The following External Interrupts are available on the Arduino:
|
||||
Arduino
|
||||
Pin* PORT INT ATmega2560 pin
|
||||
21 PD0 0 43
|
||||
20 PD1 1 44
|
||||
19 PD2 2 45
|
||||
18 PD3 3 46
|
||||
2 PE4 4 6
|
||||
3 PE5 5 7
|
||||
n/c PE6 6 8 (fake pin 75)
|
||||
n/c PE7 7 9 (fake pin 76)
|
||||
|
||||
...it is recommended to first disable INTn by clearing its Interrupt Enable bit in the
|
||||
EIMSK Register. Then, the ISCn bit can be changed. Finally, the INTn interrupt flag should be
|
||||
cleared by writing a logical one to its Interrupt Flag bit (INTFn) in the EIFR Register before the
|
||||
interrupt is re-enabled.
|
||||
|
||||
EICRA: 7 6 5 4 3 2 1 0 (External Interrupt Control Register A)
|
||||
ISC: 31 30 21 20 11 10 01 00 Interrupt Sense Control Bits
|
||||
rw rw rw rw rw rw rw rw
|
||||
|
||||
EICRB: 7 6 5 4 3 2 1 0 (External Interrupt Control Register B)
|
||||
ISC: 71 70 61 60 51 50 41 40 Interrupt Sense Control Bits
|
||||
rw rw rw rw rw rw rw rw NOTE: NO CONNECTION for INT6 and INT7 on ATmega2560**
|
||||
|
||||
ISCx1 / ISCx0 : INTx
|
||||
0 0 Low
|
||||
0 1 Change
|
||||
1 0 Falling
|
||||
1 1 Rising
|
||||
|
||||
EIMSK: 7 6 5 4 3 2 1 0 (External Interrupt Mask Register)
|
||||
n n n n n n n n NOTE: NO CONNECTION FOR INT6 and INT7 on ATmega2560**
|
||||
rw rw rw rw rw rw rw rw
|
||||
n= INTn number
|
||||
|
||||
External Interrupt Flag Register is set to 1 when a signal generates an IRQ.
|
||||
Cleared upon entering the ISR. Can be cleared by writing a 1 to it.
|
||||
EIFR: 7 6 5 4 3 2 1 0 (External Interrupt Flag Register)
|
||||
n n n n n n n n NOTE: NO CONNECTION FOR INT6 and INT7 on ATmega2560**
|
||||
rw rw rw rw rw rw rw rw
|
||||
n= INTn number
|
||||
|
||||
** But that doesn't mean they wouldn't make an excellent resource for software interrupts! ;-) )
|
||||
|
||||
Pin Change Interrupts ---------------------------------------------------------------------------
|
||||
|
||||
ATMEGA2560 Pin Change Interrupts
|
||||
Arduino Arduino Arduino
|
||||
Pin* PORT PCINT Pin PORT PCINT Pin PORT PCINT
|
||||
A8 PK0 16 10 PB4 4 SS PB0 0
|
||||
A9 PK1 17 11 PB5 5 SCK PB1 1
|
||||
A10 PK2 18 12 PB6 6 MOSI PB2 2
|
||||
A11 PK3 19 13 PB7 7 MISO PB3 3
|
||||
A12 PK4 20 14 PJ1 10
|
||||
A13 PK5 21 15 PJ0 9
|
||||
A14 PK6 22 0 PE0 8 - this one is a little odd.*
|
||||
A15 PK7 23
|
||||
...indeed, the ATmega2560 chip supports many more Pin Change Interrupt pins but
|
||||
they are unavailable on the Arduino, unless you want to solder teeny tiny wires.
|
||||
(However, that doesn't mean they wouldn't make an excellent resource for software interrupts! :-) )
|
||||
|
||||
* Note: Arduino Pin 0 is PE0 (PCINT8), which is RX0. Also, it is the only other
|
||||
pin on another port on PCI1. This would make it very costly to integrate with
|
||||
the library's code and thus is not supported by this library. It is the same
|
||||
pin the Arduino uses to upload sketches, and it is connected to the FT232RL
|
||||
USB-to-Serial chip (ATmega16U2 on the R3).
|
||||
|
||||
static const uint8_t SS = 53;
|
||||
static const uint8_t MOSI = 51;
|
||||
static const uint8_t MISO = 50;
|
||||
static const uint8_t SCK = 52;
|
||||
static const uint8_t A8 = 62;
|
||||
static const uint8_t A9 = 63;
|
||||
static const uint8_t A10 = 64;
|
||||
static const uint8_t A11 = 65;
|
||||
static const uint8_t A12 = 66;
|
||||
static const uint8_t A13 = 67;
|
||||
static const uint8_t A14 = 68;
|
||||
static const uint8_t A15 = 69;
|
||||
|
||||
|
||||
|
||||
// PIN CHANGE INTERRUPTS REGISTER BESTIARY for the ATmega2560
|
||||
|
||||
PCICR: 7 6 5 4 3 2 1 0 (When PCIE2 is set and GIE is set, PCI2 is enabled)
|
||||
PCIE2 1 0 Likewise for 1 and 0.
|
||||
- - - - - rw rw rw
|
||||
|
||||
// set...
|
||||
PCIFR: 7 6 5 4 3 2 1 0 (When logic change triggers IRQ, bececomes set. Cleared when
|
||||
PCIF2 1 0 IRQ is executed. PCIF2 == PCIE2, etc.)
|
||||
- - - - - rw rw rw
|
||||
|
||||
PCMSK2:7 6 5 4 3 2 1 0 (Selects whether pin change interrupt is enabled on PCINT23:16
|
||||
PCINT23 ... PCINT16 If PCIE2 in PCICR and this bit is set, it is enabled on that
|
||||
rw rw rw rw rw rw rw rw pin.)
|
||||
PK7 PK6 PK5 PK4 PK3 PK2 PK1 PK0 =PORTK
|
||||
+ + + + + + + + + == available on the Arduino board.
|
||||
|
||||
PCMSK1:7 6 5 4 3 2 1 0 (Selects whether pin change interrupt is enabled on PCINT15:8
|
||||
PCINT15 ... PCINT8 If PCIE1 in PCICR and this bit is set, it is enabled on that
|
||||
rw rw rw rw rw rw rw rw pin.)
|
||||
PJ6 PJ5 PJ4 PJ3 PJ2 PJ1 PJ0 PE0 =PORTJ/E Note pin PE0 is the Arduino's RX pin for programming.
|
||||
+ + +
|
||||
|
||||
PCMSK0:7 6 5 4 3 2 1 0 (Selects whether pin change interrupt is enabled o2560n PCINT7:0
|
||||
PCINT7 ... PCINT0 If PCIE0 in PCICR and this bit is set, it is enabled on that
|
||||
rw rw rw rw rw rw rw rw pin.)
|
||||
PB7 PB6 PB5 PB4 PB3 PB2 PB1 PB0 =PORTB
|
||||
+ + + + + + + +
|
||||
|
||||
=====================================================================================================
|
||||
=====================================================================================================
|
||||
ATmega644 / 1284 Support (MIGHTY1284 used as a reference, NOT Sanguino)
|
||||
=====================================================================================================
|
||||
=====================================================================================================
|
||||
// Sanguino, Mosquino uino bobino bonanafannafofino, me my momino...
|
||||
#if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)
|
||||
|
||||
// Here I use the mighty-1284p pinout from https://maniacbug.wordpress.com/2011/11/27/arduino-on-atmega1284p-4/
|
||||
+---\/---+
|
||||
(D 0) PB0 |1 40| PA0 (AI 0 / D24)
|
||||
(D 1) PB1 |2 39| PA1 (AI 1 / D25)
|
||||
INT2 (D 2) PB2 |3 38| PA2 (AI 2 / D26)
|
||||
PWM (D 3) PB3 |4 37| PA3 (AI 3 / D27)
|
||||
PWM SS (D 4) PB4 |5 36| PA4 (AI 4 / D28)
|
||||
MOSI (D 5) PB5 |6 35| PA5 (AI 5 / D29)
|
||||
PWM MISO (D 6) PB6 |7 34| PA6 (AI 6 / D30)
|
||||
PWM SCK (D 7) PB7 |8 33| PA7 (AI 7 / D31)
|
||||
RST |9 32| AREF
|
||||
VCC |10 31| GND
|
||||
GND |11 30| AVCC
|
||||
XTAL2 |12 29| PC7 (D 23)
|
||||
XTAL1 |13 28| PC6 (D 22)
|
||||
RX0 (D 8) PD0 |14 27| PC5 (D 21) TDI
|
||||
TX0 (D 9) PD1 |15 26| PC4 (D 20) TDO
|
||||
INT0 RX1 (D 10) PD2 |16 25| PC3 (D 19) TMS
|
||||
INT1 TX1 (D 11) PD3 |17 24| PC2 (D 18) TCK
|
||||
PWM (D 12) PD4 |18 23| PC1 (D 17) SDA
|
||||
PWM (D 13) PD5 |19 22| PC0 (D 16) SDL
|
||||
PWM (D 14) PD6 |20 21| PD7 (D 15) PWM
|
||||
+--------+
|
||||
|
||||
External Interrupts ------------------------------------------------------------------------------
|
||||
The following External Interrupts are available on the Sanguino:
|
||||
Sanguino
|
||||
Pin* PORT INT ATmega644/1284 pin
|
||||
2 PB2 2 3
|
||||
10 PD2 0 16
|
||||
11 PD3 1 17
|
||||
|
||||
The following Pin Change Interrupts are available on the ATmega1284p:
|
||||
Mighty Mighty
|
||||
Pin* PORT PCINT ATmega644/1284 pin Pin* PORT PCINT ATmega644/1284 pin
|
||||
0 PB0 8 1 15 PD7 31 21
|
||||
1 PB1 9 2 16 PC0 16 22
|
||||
2 PB2 2 3 17 PC1 17 23
|
||||
3 PB3 11 4 18 PC2 18 24
|
||||
4 PB4 12 5 19 PC3 19 25
|
||||
5 PB5 13 6 20 PC4 20 26
|
||||
6 PB6 14 7 21 PC5 21 27
|
||||
7 PB7 15 8 22 PC6 22 28
|
||||
8 PD0 24 14 23 PC7 23 29
|
||||
9 PD1 25 15 31/A7 PA7 7 33
|
||||
10 PD2 26 16 30/A6 PA6 6 34
|
||||
11 PD3 27 17 29/A5 PA5 5 35
|
||||
12 PD4 28 18 28/A4 PA4 4 36
|
||||
13 PD5 29 19 27/A3 PA3 3 37
|
||||
14 PD6 30 20 26/A2 PA2 2 38
|
||||
25/A1 PA1 1 39
|
||||
24/A0 PA0 0 40
|
||||
|
||||
EICRA: 7 6 5 4 3 2 1 0 (External Interrupt Control Register A)
|
||||
ISC: - - 21 20 11 10 01 00 Interrupt Sense Control Bits (ISCxx)
|
||||
r r rw rw rw rw rw rw
|
||||
|
||||
EIMSK: 7 6 5 4 3 2 1 0 (External Interrupt Mask Register)
|
||||
- - - - - n n n NOTE: NO CONNECTION FOR INT6 and INT7 on ATmega2560**
|
||||
r r r r r rw rw rw
|
||||
n= INTn number
|
||||
|
||||
EIFR: External Interrupt Flag Register is set to 1 when a signal generates an IRQ.
|
||||
Cleared upon entering the ISR. Can be cleared by writing a 1 to it.
|
||||
EIFR: 7 6 5 4 3 2 1 0 (External Interrupt Flag Register)
|
||||
- - - - - n n n NOTE: NO CONNECTION FOR INT6 and INT7 on ATmega2560**
|
||||
rw r r r rw rw rw rw
|
||||
n= INTn number
|
||||
|
||||
PCICR: 7 6 5 4 3 2 1 0 (When PCIE2 is set and GIE is set, PCI2 is enabled)
|
||||
PCIE3 2 1 0 Likewise for 1 and 0.
|
||||
r r r r rw rw rw rw
|
||||
|
||||
PCIFR: 7 6 5 4 3 2 1 0 (When logic change triggers IRQ, becomes set. Cleared when
|
||||
PCIF3 2 1 0 IRQ is executed. PCIF2 == PCIE2, etc.)
|
||||
r r r r rw rw rw rw
|
||||
|
||||
0x73
|
||||
PCMSK3:7 6 5 4 3 2 1 0 (Selects whether pin change interrupt is enabled on PCINT23:16
|
||||
PCINT31 ... PCINT24 If PCIE2 in PCICR and this bit is set, it is enabled on that
|
||||
rw rw rw rw rw rw rw rw pin.)
|
||||
PD7 PD6 PD5 PD4 PD3 PD2 PD1 PD0 =PORTD
|
||||
15 14 13 12 11 10 09 08 -->Sanguino Pins, DIP40 package
|
||||
|
||||
0x6D
|
||||
PCMSK2:7 6 5 4 3 2 1 0 (Selects whether pin change interrupt is enabled on PCINT23:16
|
||||
PCINT23 ... PCINT16 If PCIE2 in PCICR and this bit is set, it is enabled on that
|
||||
rw rw rw rw rw rw rw rw pin.)
|
||||
PC7 PC6 PC5 PC4 PC3 PC2 PC1 PC0 =PORTC
|
||||
23 22 21 20 19 18 17 16 -->Sanguino Pins, DIP40 package
|
||||
|
||||
PCMSK1:7 6 5 4 3 2 1 0 (Selects whether pin change interrupt is enabled on PCINT15:8
|
||||
PCINT15 ... PCINT8 If PCIE1 in PCICR and this bit is set, it is enabled on that
|
||||
rw rw rw rw rw rw rw rw pin.)
|
||||
PB7 PB6 PB5 PB4 PB3 PB2 PB1 PB0 =PORTB
|
||||
7 6 5 4 3 2 1 0 -->Sanguino Pins, DIP40 package
|
||||
|
||||
PCMSK0:7 6 5 4 3 2 1 0 (Selects whether pin change interrupt is enabled o2560n PCINT7:0
|
||||
PCINT7 ... PCINT0 If PCIE0 in PCICR and this bit is set, it is enabled on that
|
||||
rw rw rw rw rw rw rw rw pin.)
|
||||
PA7 PA6 PA5 PA4 PA3 PA2 PA1 PA0 =PORTB
|
||||
24 25 26 27 28 29 30 31 -->Sanguino Pins, DIP40 package
|
||||
|
||||
|
||||
=====================================================================================================
|
||||
=====================================================================================================
|
||||
ATtiny 24/44/84 support ATTINY24
|
||||
=====================================================================================================
|
||||
=====================================================================================================
|
||||
Only the 44/84 are supported.
|
||||
|
||||
Support for this chip is based on David Mellis' work at https://github.com/damellis/attiny
|
||||
This is an ATmega that comes in a 14-pin configuration. There are two ports, A and B. PCint pins are
|
||||
configured on both ports. The following is the pinout, and shows the Arduino pin numbering scheme:
|
||||
// ATtiny24/44/84 / ARDUINO
|
||||
//
|
||||
// +-\/-+
|
||||
// VCC 1| |14 GND
|
||||
// (D 10) PB0 2| |13 PA0 (D 0) == AREF
|
||||
// (D 9) PB1 3| |12 PA1 (D 1)
|
||||
// PB3 4| |11 PA2 (D 2)
|
||||
// PWM INT0 (D 8) PB2 5| |10 PA3 (D 3)
|
||||
// PWM (D 7) PA7 6| |9 PA4 (D 4)
|
||||
// PWM (D 6) PA6 7| |8 PA5 (D 5) PWM
|
||||
// +----+
|
||||
|
||||
gcc CPU designations are as follows:
|
||||
__AVR_ATtiny24__ __AVR_ATtiny24A__ __AVR_ATtiny44__ __AVR_ATtiny44A__
|
||||
__AVR_ATtiny84__ __AVR_ATtiny84A__
|
||||
|
||||
The following External Interrupts are available on the ATtiny24/44/84:
|
||||
Arduino(tiny)
|
||||
Pin* PORT INT ATtiny44/84 pin
|
||||
8 PB2 0 5
|
||||
|
||||
The following Pin Change Interrupts are available on the ATmega24/44/84:
|
||||
Arduino(tiny) Arduino(tiny)
|
||||
Pin* PORT PCINT ATmega24/44/84 pin Pin* PORT PCINT ATmega24/44/84 pin
|
||||
0 PA0 0 13 5 PA5 5 8
|
||||
1 PA1 1 12 6 PA6 6 7
|
||||
2 PA2 2 11 7 PA7 7 6
|
||||
3 PA3 3 10 8 PB2 10 5
|
||||
4 PA4 4 9 9 PB1 9 3
|
||||
10 PB0 8 2
|
||||
"fake" 11 PB3 11 4
|
||||
|
||||
Interrupt registers are different on the Tiny series. Interrupts are set by MCUCR, GIMSK, GIFR, PCMSK0, and PCMSK1.
|
||||
|
||||
EXTERNAL INTERRUPTS
|
||||
-------------------
|
||||
MCUCR:
|
||||
ISC: - - - - - - 01 00 Interrupt Sense Control Bits (ISCxx)
|
||||
rw rw rw rw rw rw rw rw
|
||||
ISC01 00
|
||||
|
||||
INT0 "is activated if the SREG I-flag and the MCUCR mask is set" (but see GIMSK, below).
|
||||
ISC01 ISC00
|
||||
0 0 INT0 interrupted on LOW level
|
||||
1 1 INT0 interrupted on CHANGE
|
||||
0 0 INT0 interrupted on FALLING
|
||||
1 1 INT0 interrupted on RISING
|
||||
|
||||
GIMSK:
|
||||
When INT0 == 1 and SREG I-flag set, External Interrupt enabled.
|
||||
When PCIE1 == 1 and SREG I-flag set, pin change Interrupt PCINT11:8 enabled.
|
||||
When PCIE0 == 1 and SREG I-flag set, pin change Interrupt PCINT7:0 enabled.
|
||||
- INT0 PCIE0 - - - -
|
||||
PCIE1
|
||||
rw rw rw rw rw rw rw rw
|
||||
--------------------------------
|
||||
|
||||
|
||||
GIFR: 7 6 5 4 3 2 1 0 (When logic change triggers IRQ, becomes set. Cleared when
|
||||
INTF0 PCIF0 2 1 0 IRQ is executed. INTF0 == INT0, etc.)
|
||||
- PCIF1 - - - - INT0 is always cleared when INT0 is a LOW interrupt
|
||||
r rw rw rw r r r r
|
||||
|
||||
PCMSK1:7 6 5 4 3 2 1 0 (Selects whether pin change interrupt is enabled on PCINT15:8
|
||||
PCINT11 ... PCINT8 If PCIE1 in GIMSK and this bit is set, it is enabled on that
|
||||
r r r r rw rw rw rw pin.)
|
||||
- - - - PB3 PB2 PB1 PB0 =PORTB
|
||||
- - - - 4 5 3 2 -->ATtiny 24/44/84 Pins, DIP14 package
|
||||
- - - - 11* 8 9 10 -->Arduino Pins, DIP14 package. * - "Fake" Arduino pin.
|
||||
|
||||
PCMSK0:7 6 5 4 3 2 1 0 (Selects whether pin change interrupt is enabled on PCINT7:0
|
||||
PCINT7 ... PCINT0 If PCIE0 in GIMSK and this bit is set, it is enabled on that
|
||||
rw rw rw rw rw rw rw rw pin.)
|
||||
PA7 PA6 PA5 PA4 PA3 PA2 PA1 PA0 =PORTA
|
||||
7 6 5 4 3 2 1 1 -->ATtiny 24/44/84 Pins, DIP14 package
|
||||
6 7 8 9 10 11 12 13 -->Arduino Pins, DIP14 package. * - "Fake" Arduino pin.
|
||||
|
||||
=====================================================================================================
|
||||
=====================================================================================================
|
||||
ATtiny 25/45/85 support ATTINY25
|
||||
=====================================================================================================
|
||||
=====================================================================================================
|
||||
Only the ATtiny 45/85 are supported.
|
||||
Support for this chip is based on David Mellis' work at https://github.com/damellis/attiny
|
||||
This is an ATmega that comes in an 8-pin configuration. There is a single port, B.
|
||||
|
||||
gcc CPU designations are as follows:
|
||||
__AVR_ATtiny25__ __AVR_ATtiny45__ __AVR_ATtiny85__
|
||||
|
||||
The following is the pinout, and shows the Arduino pin numbering scheme:
|
||||
// ATtiny25/45/85 / ARDUINO
|
||||
//
|
||||
// +-\/-+
|
||||
// (D 5) PB5 1| |8 Vcc
|
||||
// (D 3) PB3 2| |7 PB2 (D 2) (INT0) (== Gemma B2)
|
||||
// (D 4) PB4 3| |6 PB1 (D 1) (== Gemma B1)
|
||||
// GND 4| |5 PB0 (D 0) (== Gemma B0)
|
||||
// +----+
|
||||
|
||||
The following External Interrupts are available on the ATtiny25/45/85:
|
||||
Arduino(tiny)
|
||||
Pin* PORT INT ATtiny25/45/85 pin
|
||||
2 PB2 0 7
|
||||
|
||||
The following Pin Change Interrupts are available on the ATmega25/45/85:
|
||||
Arduino(tiny) Arduino(tiny)
|
||||
Pin* PORT PCINT ATmega25/45/85 pin Pin* PORT PCINT ATmega25/45/85 pin
|
||||
0 PB0 0 5 3 PB3 3 2
|
||||
1 PB1 1 6 4 PB4 4 3
|
||||
2 PB2 2 7 5 PB5 5 1
|
||||
|
||||
Interrupt registers are different on the Tiny series. Interrupts are set by MCUCR, GIMSK, GIFR, PCMSK0, and PCMSK1.
|
||||
|
||||
|
||||
MCUCR:
|
||||
ISC: - - - - - - 01 00 Interrupt Sense Control Bits (ISCxx)
|
||||
rw rw rw rw rw rw rw rw
|
||||
ISC01 00
|
||||
|
||||
INT0 "is activated if the SREG I-flag and the MCUCR mask is set" (but see GIMSK, below).
|
||||
ISC01 ISC00
|
||||
0 0 INT0 interrupted on LOW level
|
||||
1 1 INT0 interrupted on CHANGE
|
||||
0 0 INT0 interrupted on FALLING
|
||||
1 1 INT0 interrupted on RISING
|
||||
|
||||
GIMSK:
|
||||
When INT0 == 1 and SREG I-flag set, External Interrupt enabled.
|
||||
When PCIE == 1 and SREG I-flag set, pin change Interrupt PCINT5:0 enabled.
|
||||
- INT0 - - - - -
|
||||
PCIE
|
||||
r rw rw r r r r r
|
||||
--------------------------------
|
||||
|
||||
|
||||
GIFR: 7 6 5 4 3 2 1 0 (When logic change triggers IRQ, becomes set. Cleared when
|
||||
INT0 IRQ is executed. INT0 == INT0, etc.)
|
||||
- PCIE - - - - - INT0 is always cleared when INT0 is a LOW interrupt
|
||||
r rw rw r r r r r
|
||||
|
||||
PCMSK :7 6 5 4 3 2 1 0 (Selects whether pin change interrupt is enabled on PCINT7:0
|
||||
PCINT5 ... PCINT0 If PCIE0 in GIMSK and this bit is set, it is enabled on that
|
||||
rw rw rw rw rw rw rw rw pin.)
|
||||
- - PB5 PB4 PB3 PB2 PB1 PB0 =PORTB
|
||||
1 3 2 7 6 5 -->ATtiny 25/45/85 Pins, DIP8 package
|
||||
|
||||
|
||||
=================================================================================================================
|
||||
From http://www.atmel.com/Images/doc8468.pdf:
|
||||
|
||||
External interrupts can be sensed and registered either synchronously or asynchronously. Synchronous sensing
|
||||
requires I/O clock whereas asynchronous sensing does not requires I/O clock. This implies that the interrupts
|
||||
that are detected asynchronously can be used for waking the device from sleep modes other than idle
|
||||
mode because the I/O clock is halted in all sleep modes except idle mode. The sense configuration for
|
||||
external interrupts and pin change interrupts for Atmel ATmega2560 is given in Table 2-2. For device
|
||||
specific sense configuration, please refer to the respective datasheet.
|
||||
|
||||
Table 2-2. External interrupts sense configuration.
|
||||
Program address Interrupt source Sensing
|
||||
$0002 INT0 Asynchronous (Edges and level)
|
||||
$0004 INT1 Asynchronous (Edges and level)
|
||||
$0006 INT2 Asynchronous (Edges and level)
|
||||
$0008 INT3 Asynchronous (Edges and level)
|
||||
$000A INT4 Synchronous (Edges and level)
|
||||
$000C INT5 Synchronous (Edges and level)
|
||||
$000E INT6 Synchronous (Edges and level)
|
||||
$0010 INT7 Synchronous (Edges and level)
|
||||
$0012 PCINT0 Asynchronous
|
||||
$0014 PCINT1 Asynchronous
|
||||
$0016 PCINT2 Asynchronous
|
||||
From Table 2-2, all the pin change interrupts are detected asynchronously.
|
||||
|
||||
...
|
||||
The interrupt execution response for all the enabled AVR interrupts is four/five clock cycle’s minimum.
|
||||
This four/five clock cycles depends on the program counter width. If the program counter width is not
|
||||
more than two bytes, then the interrupt response time will be four clock cycles minimum and if the
|
||||
program counter width is more than two bytes, then the interrupt response time will be minimum five
|
||||
clock cycles. These four/five clock cycles include:
|
||||
1. Two/Three cycles for pushing the Program Counter (PC) value into the stack.
|
||||
2. One cycle for updating the stack pointer.
|
||||
3. One cycle for clearing the Global interrupt enable (I) bit.
|
||||
If an interrupt occurs when the MCU is in sleep mode, the interrupt execution response time is increased
|
||||
by five clock cycles. This increase comes in addition to the start-up time from the selected sleep mode.
|
||||
This start up time is the time it will take to start the clock source.
|
||||
|
||||
=====================================================================================================
|
||||
ARDUINO CPU BESTIARY
|
||||
=====================================================================================================
|
||||
See /usr/avr/include/avr/io.h for the actual #defines for the different CPUs.
|
||||
The CPUs are converted to the #defined macros (eg., __AVR_ATmega169__) by the compiler from
|
||||
the source file "avr-mcus.def". See
|
||||
https://github.com/gcc-mirror/gcc/blob/master/gcc/config/avr/avr-mcus.def
|
||||
|
||||
$ grep mcu /usr/share/arduino/hardware/arduino/boards.txt
|
||||
uno.build.mcu=atmega328p
|
||||
atmega328.build.mcu=atmega328p
|
||||
diecimila.build.mcu=atmega168
|
||||
nano328.build.mcu=atmega328p
|
||||
nano.build.mcu=atmega168
|
||||
mega2560.build.mcu=atmega2560
|
||||
mega.build.mcu=atmega1280
|
||||
leonardo.build.mcu=atmega32u4
|
||||
esplora.build.mcu=atmega32u4
|
||||
micro.build.mcu=atmega32u4
|
||||
mini328.build.mcu=atmega328p
|
||||
mini.build.mcu=atmega168
|
||||
ethernet.build.mcu=atmega328p
|
||||
fio.build.mcu=atmega328p
|
||||
bt328.build.mcu=atmega328p
|
||||
bt.build.mcu=atmega168
|
||||
LilyPadUSB.build.mcu=atmega32u4
|
||||
lilypad328.build.mcu=atmega328p
|
||||
lilypad.build.mcu=atmega168
|
||||
pro5v328.build.mcu=atmega328p
|
||||
pro5v.build.mcu=atmega168
|
||||
pro328.build.mcu=atmega328p
|
||||
pro.build.mcu=atmega168
|
||||
atmega168.build.mcu=atmega168
|
||||
atmega8.build.mcu=atmega8
|
||||
robotControl.build.mcu=atmega32u4
|
||||
robotMotor.build.mcu=atmega32u4
|
||||
|
||||
ISR Register handling
|
||||
|
||||
Tested the following code to ensure that all registers would be pushed/popped correctly, even
|
||||
if I was using NAKED_ISR. Note that I did not run code, I merely eyeballed the output to ensure
|
||||
it was doing what I expected:
|
||||
|
||||
volatile uint8_t storage0;
|
||||
volatile uint8_t storage1;
|
||||
volatile uint8_t storage2;
|
||||
volatile uint8_t storage3;
|
||||
volatile uint8_t storage4;
|
||||
volatile uint8_t storage5;
|
||||
volatile uint8_t storage6;
|
||||
volatile uint8_t storage7;
|
||||
volatile uint8_t storage8;
|
||||
volatile uint8_t storage9;
|
||||
volatile uint8_t storage10;
|
||||
volatile uint8_t storage11;
|
||||
volatile uint8_t storage12;
|
||||
volatile uint8_t storage13;
|
||||
volatile uint8_t storage14;
|
||||
volatile uint8_t storage15;
|
||||
volatile uint8_t storage16;
|
||||
volatile uint8_t storage17;
|
||||
volatile uint8_t storage18;
|
||||
volatile uint8_t storage19;
|
||||
|
||||
void test_ISR(uint8_t current) {
|
||||
|
||||
uint8_t local0=storage0;
|
||||
uint8_t local1=storage1;
|
||||
uint8_t local2=storage2;
|
||||
uint8_t local3=storage3;
|
||||
uint8_t local4=storage4;
|
||||
uint8_t local5=storage5;
|
||||
uint8_t local6=storage6;
|
||||
uint8_t local7=storage7;
|
||||
uint8_t local8=storage8;
|
||||
uint8_t local9=storage9;
|
||||
uint8_t local10=storage10;
|
||||
uint8_t local11=storage11;
|
||||
uint8_t local12=storage12;
|
||||
uint8_t local13=storage13;
|
||||
uint8_t local14=storage14;
|
||||
uint8_t local15=storage15;
|
||||
uint8_t local16=storage16;
|
||||
uint8_t local17=storage17;
|
||||
uint8_t local18=storage18;
|
||||
uint8_t local19=storage19;
|
||||
|
||||
local0+=current;
|
||||
local1+=current;
|
||||
local2+=current;
|
||||
local3+=current;
|
||||
local4+=current;
|
||||
local5+=current;
|
||||
local6+=current;
|
||||
local7+=current;
|
||||
local8+=current;
|
||||
local9+=current;
|
||||
local10+=current;
|
||||
local11+=current;
|
||||
local12+=current;
|
||||
local13+=current;
|
||||
local14+=current;
|
||||
local15+=current;
|
||||
local16+=current;
|
||||
local17+=current;
|
||||
local18+=current;
|
||||
local19+=current;
|
||||
|
||||
storage0=local0;
|
||||
storage1=local1;
|
||||
storage2=local2;
|
||||
storage3=local3;
|
||||
storage4=local4;
|
||||
storage5=local5;
|
||||
storage6=local6;
|
||||
storage7=local7;
|
||||
storage8=local8;
|
||||
storage9=local9;
|
||||
storage10=local10;
|
||||
storage11=local11;
|
||||
storage12=local12;
|
||||
storage13=local13;
|
||||
storage14=local14;
|
||||
storage15=local15;
|
||||
storage16=local16;
|
||||
storage17=local17;
|
||||
storage18=local18;
|
||||
storage19=local19;
|
||||
}
|
||||
|
||||
ISR(PORTD_VECT, ISR_NAKED) {
|
||||
register uint8_t current asm("r18");
|
||||
EI_ASM_PREFIX(PIND);
|
||||
|
||||
test_ISR(current);
|
||||
|
||||
EI_ASM_SUFFIX;
|
||||
}
|
||||
|
||||
MISCELLANEOUS:
|
||||
STORING FUNCTION POINTERS IN PROGMEM:
|
||||
http://stackoverflow.com/questions/28261595/put-progmem-function-pointer-array-into-another-progmem-array
|
||||
|
||||
|
||||
Calling the function pointers by checking each pin's bitmask individually:
|
||||
|
||||
if (interruptMask & _BV(0)) functionPointerB0(); Cycles
|
||||
8b8: c0 ff sbrs r28, 0 1 if move on, 2 if skip (to 8bc)
|
||||
8ba: 05 c0 rjmp .+10 2 (move on)
|
||||
8bc: e0 91 60 02 lds r30, 0x0260 2
|
||||
8c0: f0 91 61 02 lds r31, 0x0261 2
|
||||
8c4: 19 95 eicall 4
|
||||
8c6: (move on) TOTAL: 10 if matches, 3 if not
|
||||
== 21 cycles till get to last function call,
|
||||
then 10 cycles to execute it: 31 cycles
|
||||
|
||||
If an interrupt on third pin:
|
||||
2 x 3 (not matched) + 10 == 16, plus
|
||||
4 x 3 (not matched) = 28 total.
|
||||
|
||||
Calling the function pointers referred to in an array, using while loop:
|
||||
|
||||
8c6: d0 e0 ldi r29, 0x00 ; 0 this is the "i" variable
|
||||
|
||||
while (1) {
|
||||
if (interruptMask & 0x01) {
|
||||
8c8: c0 ff sbrs r28, 0 1 if it's not set, 2 if skip
|
||||
8ca: 0a c0 rjmp .+20 2 (move on to try next bit at 0x8e0)
|
||||
(*functionPointerArray[i])();
|
||||
8cc: ed 2f mov r30, r29 1 (it's set, execute the function)
|
||||
8ce: f0 e0 ldi r31, 0x00 1 ; loads 0
|
||||
8d0: ee 0f add r30, r30 1
|
||||
8d2: ff 1f adc r31, r31 1
|
||||
8d4: e7 57 subi r30, 0x77 1 ; 119
|
||||
8d6: fd 4f sbci r31, 0xFD 1 ; 253
|
||||
8d8: 01 90 ld r0, Z+ 1 load from data memory
|
||||
8da: f0 81 ld r31, Z 1
|
||||
8dc: e0 2d mov r30, r0 1
|
||||
8de: 19 95 eicall 4
|
||||
}
|
||||
interruptMask=interruptMask >> 1;
|
||||
8e0: c6 95 lsr r28 1
|
||||
if (interruptMask == 0) goto exitISR;
|
||||
8e2: 11 f0 breq .+4 1 if not zero, 2 if zero (jumps out...) ; 0x8e8 <__vector_9+0x86>
|
||||
i++;
|
||||
8e4: df 5f subi r29, 0xFF 1 ; 255
|
||||
8e6: f0 cf rjmp .-32 2 ; 0x8c8 <__vector_9+0x66>
|
||||
|
||||
TOTAL: 14 if matches, 9 if not
|
||||
== 63 cycles to get to last function call,
|
||||
then 14 cycles to execute it: 77 cycles
|
||||
|
||||
If an interrupt on third pin:
|
||||
2 x 7 (not matched) == 14 + 14 == 28 total.
|
||||
Then a couple of cycles to get out.
|
||||
|
||||
|
||||
===========================================================================================================
|
||||
Space Optimizations
|
||||
===========================================================================================================
|
||||
Compile Simple.ino, using pin 10, compile for ATmega2560:
|
||||
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)
|
||||
|
المرجع في مشكلة جديدة
حظر مستخدم