$REDUCEIVR

Top  Previous  Next

Action

This directive will inform the compiler to reduce the IVR (interrupt vector table) to the smallest possible size.

 

 

Syntax

$REDUCEIVR

 

 

Remarks

The flash memory of the processor always starts with the IVR (interrupt vector table). The user code is placed after this table.

So what is this IVR ?

This table contains an address for each interrupt. When an interrupt occurs, the processor will jump to a specific and fixed address in code memory.

The address depends on the interrupt itself, and on the processor. For example the MEGA88 has 25 interrupt sources. You can find them in the dat file :

 

INTname1=INT0,$001,EIMSK.INT0,EIFR.INTF0

INTname2=INT1,$002,EIMSK.INT1,EIFR.INTF1

INTname3=PCINT0,$003,PCICR.PCIE0,PCIFR.PCIF0

INTname4=PCINT1,$004,PCICR.PCIE1,PCIFR.PCIF1

INTname5=PCINT2,$005,PCICR.PCIE2,PCIFR.PCIF2

INTname6=WDT@WATCHDOG,$006,WDTCSR.WDIE,WDTCSR.WDIF

INTname7=OC2A@COMPARE2A,$007,TIMSK2.OCIE2A,TIFR2.OCF2A

INTname8=OC2B@COMPARE2B,$008,TIMSK2.OCIE2B,TIFR2.OCF2B

INTname9=OVF2@TIMER2,$009,TIMSK2.TOIE2,TIFR2.TOV2

INTname10=ICP1@CAPTURE1,$00A,TIMSK1.TICIE1,TIFR1.ICF1

INTname11=OC1A@COMPARE1A,$00B,TIMSK1.OCIE1A,TIFR1.OCF1A

INTname12=OC1B@COMPARE1B,$00C,TIMSK1.OCIE1B,TIFR1.OCF1B

INTname13=OVF1@TIMER1,$00D,TIMSK1.TOIE1,TIFR1.TOV1

INTname14=OC0A@COMPARE0A,$00E,TIMSK0.OCIE0A,TIFR0.OCF0A

INTname15=OC0B@COMPARE0B,$00F,TIMSK0.OCIE0B,TIFR0.OCF0B

INTname16=OVF0@TIMER0,$010,TIMSK0.TOIE0,TIFR0.TOV0

INTname17=SPI,$011,SPCR.SPIE,SPSR.SPIF

INTname18=URXC@SERIAL,$012,UCSR0B.RXCIE0,UCSR0A.RXC0

INTname19=UDRE,$013,UCSR0B.UDRIE0,UCSR0A.UDRE0

INTname20=UTXC,$014,UCSR0B.TXCIE0,UCSR0A.TXC0

INTname21=ADCC@ADC,$015,ADCSRA.ADIE,ADCSRA.ADIF

INTname22=ERDY,$016,EECR.EERIE

INTname23=ACI,$017,ACSR.ACIE,ACSR.ACI

INTname24=TWI,$018,TWCR.TWIE,TWCR.TWINT

INTname25=SPM,$019,SPMCSR.SPMIE

 

You can see that INT0 comes first. And that the address is $001 which is &H0001. So when INT0 occurs, the processor will jump to address 1.

When you did not define an ISR (ON INT0) , the compiler will insert a RETI instruction. So nothing bad will happen to your code.

When you did define an ISR , the compiler will insert a JUMP to your interrupt routine. When your interrupt ends, the RETI will let the processor continue where it was when the interrupt occurred.

In the example when we only use the ISR with the lowest address all other addresses in the table would get a RETI instruction. And the user code could start at &H1A (one address after $19).

Now that is not so bad but there are also processors with bigger tables and with tables that require 2 words for a JUMP. You waste a lot of space this way.

 

So what does $REDUCEIVR do? It will determine which interrupt you have used has the highest address. And it will use the address after that as the user code start.

This means that if we use only INT0 and we use $REDUCEIVR, the user code will start at address &H2 ($2). So you will save a lot of code space this way.

Ok so why isn't this enabled by default? There is a catch : when your code has an interrupt enabled and there is no matching ON <INT> the processor will jump into the user code and this will create a crash almost for sure.

So our advise : use this when you understand what this option does, and use it when your application is finished. In any case, retest the complete application when the option is enabled.

 

 

 

See also

$LOADER , CONFIG INTVECTORSELECTION , $BOOTVECTOR

 

 

Example

$REDUCEIVR