Interrupt latency in C

Say each time a pin changes a timer is read cleared and restarted
In assembler latency is 5 cycles and a few more when it is read.
Howmany cycles will latency be in C including the timer-read ?

Modern C compilers generally can do as good or better job at generating code than you can by using assembler directly. For the specific section of code you mention, I would not expect much difference. You could always try it and take a look at the code that's actually produced.

Have you thought of using the Input Capture Register? Then you don't have to worry about interrupt latency, or those other interrupts happening, or places where interrupts are temporarily disabled.

In the given example Inputcapture is better indeed.
But sometimes interrupt timing really has to be tight.
How about using ASM for the interrupt routine?
(assuming nothing is executed between the int and the icall.)

gbaars:
In the given example Inputcapture is better indeed.
But sometimes interrupt timing really has to be tight.
How about using ASM for the interrupt routine?
(assuming nothing is executed between the int and the icall.)

Using assembler in your ISR is not in any way going to protect you from other ISRs or code that disables interrupts.

gbaars:
Howmany cycles will latency be in C including the timer-read ?

It could vary quite a bit depending on the code since depending on the code it may have to save/restore more registers.

Best thing to do would be to compile the actual code and look at the assembler generated.

— bill

First, don't go the Arduino 'attachInterrupt()' approach. Rather, implement the function for the ISR vector yourself. Next look into 'ISR_NAKED' which will cause the processor to save fewer state variables when the interrupt fires.

If implementing everything interrupt related and
make no use of C for it could anything else affect this?

gbaars:
If implementing everything interrupt related and
make no use of C for it could anything else affect this?

You are safe if you follow the rules:
https://www.nongnu.org/avr-libc/user-manual/assembler.html

In assembler latency is 5 cycles and a few more when it is read.

Is not.

7.7.1: The interrupt execution response for all the enabled AVR interrupts is four clock cycles minimum. After four clock cycles the program vector address for the actual interrupt handling routine is executed. During this four clock cycle period, the Program Counter is pushed onto the Stack. The vector is normally a jump to the interrupt routine, and this jump takes three clock cycles.

You’ll also have to save SOME context in addition to the raw ISR overhead and the actual timer reads/writes.

How many cycles will latency be in C including the timer-read ?

Well, let’s see. For the Arduino IDE 1.8.12, I assume you mean something like:

volatile uint16_t ocCount;
ISR(TIMER0_COMPA_vect) {  // timer interrupt
  ocCount += 1;           // increment a counter
  OCR0A += 10;            // schedule next interrupt.
}

Which produces:

000005b2 <__vector_14>:
 5b2:   1f 92           push    r1              ; save r1 "known zero"
 5b4:   0f 92           push    r0
 5b6:   0f b6           in      r0, 0x3f        ; get and save flags.
 5b8:   0f 92           push    r0
 5ba:   11 24           eor     r1, r1          ; make r1 zero, just in case.
 5bc:   8f 93           push    r24             ; save registers for math on ocCount.
 5be:   9f 93           push    r25
 5c0:   80 91 b8 01     lds     r24, 0x01B8     ; 0x8001b8 <ocCount>
 5c4:   90 91 b9 01     lds     r25, 0x01B9     ; 0x8001b9 <ocCount+0x1>
 5c8:   01 96           adiw    r24, 0x01       ; 1
 5ca:   90 93 b9 01     sts     0x01B9, r25     ; 0x8001b9 <ocCount+0x1>
 5ce:   80 93 b8 01     sts     0x01B8, r24     ; 0x8001b8 <ocCount>
 5d2:   87 b5           in      r24, 0x27       ; get timer register (re-uses R24!)
 5d4:   86 5f           subi    r24, 0xF6       ; add 10
 5d6:   87 bd           out     0x27, r24       ; store.
 5d8:   9f 91           pop     r25             ; restore math registers
 5da:   8f 91           pop     r24
 5dc:   0f 90           pop     r0              ; restore flages
 5de:   0f be           out     0x3f, r0        
 5e0:   0f 90           pop     r0              ; restore r0 used for flags
 5e2:   1f 90           pop     r1              ; restore known zero, which we didn't use.
 5e4:   18 95           reti

So compared to a carefully written ASM function:

  • it wastes three instructions dealing with R1.
  • and two instuctions putting the flags on the stack, when it could have just stayed in a register.
  • you could’ve incremented ocCount one-byte at a time, avoiding a register save/restore (by adding an additional ADD instruction…)

(I believe that 1 and 2 are improved in newer versions of the compiler, BTW.)