Testing the AVR’s interrupt latency.

It would be nice if I could reduce parts count by emulating the 82C51A UART (or MC6850) using the AT90USB1286. Since the INT[7..0] interrupt pins are selectable between level or +/- edge sensitive and the pin-change interrupts will respond to ANY change of state, I will stick with the INT[7..0] pins. I want to trigger when the UART chip select goes high at which time the AVR will drop the WAIT line low to extend the read or write cycle while it services the request.

The AT90USB1286 data sheet states: “Interrupt Response Time: The interrupt execution response for all the enabled AVR interrupts is five clock cycles minimum. After five clock cycles the program vector address for the actual interrupt handling routine is executed. During these five 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. If an interrupt occurs during execution of a multi-cycle instruction, this instruction is completed before the interrupt is served. 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.

Doing some calculations, seems that at best, there will be a 5+3 cycle latency period just to set the program pointer to the first instruction of the ISR, then another 2 clock cycles to execute the instruction to drop the WAIT line pin, which makes 10 clock cycles. At 16MHz, the AVR’s clock period is 62.5nS, hence the AVR’s minimum interrupt latency will be 10 * 62.5nS or 625nS. That means that it will be at least 625nS before I can drop the Z80’s WAIT line to extend the RD/WR cycle. That won’t work since the Z80 datasheet says that the WAIT setup time must be at least 50nS before the falling edge of the clock after MREQ or IORQ goes active low and the hold time after the falling edge of the clock must be at least 10nS. With an 8MHz Z80 clock, the period is 125nS, so the AVR must be able to respond within in 75nS or less (125nS – 50nS = 75nS). Still, I would like to code up an ISR and perform some testing to see just what Z80 clock speed I can obtain a response.

My little test board is using an ATmega328P, not the AT90USB1286. The Interrupt Response Time is 1 cycle faster on the ATmega328P than the AT90USB1286. For simplicity, I have the RAM2 select connected to the INT0 pin of the ATmega328P and the WAIT pin is being driven by port bit B1. The functional code is below.

 ;initialize TIMR0 to divide the CPU clock and output it on OC0A to be
 ; used as the system clock for the Z80.
 ; At this point, the I/O ports have already be initialized and
 ; the Z80 reset pin is being held low.
    cli ;clear global IRQ's
    CLRB PORTD,Z80WS ;insure Z80WS pin low
    GoSub Delay100mS ;delay for 100mS

;Now apply the clock signal
    CLRB PRR,PRTIM0,temp ;enable TIM0 in PRR
    ldi temp,$7 ;divider rate for 1MHz
    STORE OCR0A,temp

   tst temp ;is clock 8MHz
    brne main1a ;no, branch
    SETB PORTD,Z80WS ;enable Z80WS wait-states
    ldi temp,( 1<0<2<
    STORE TCCR0A,temp
    ldi temp,( 0<1<
    STORE TCCR0B,temp

;Apply a system reset
    GoSub Delay100mS ;wait for 100mS
    SETB PORTB,Z80RST ;unleash the Z80 beast!

;setup for INT0
    ldi temp,(2<<ISC00) ;set for falling edge trigger on INT0
    STORE EICRA,temp
    SETB EIFR,INTF0 ;clear any pending INT0 interrupts
    SETB EIMSK,INT0 ;enable INT0 interrupts

    rjmp Main1z

 ; Routine to test servicing Z80 port select response. We want
 ; to stay in the ISR to block any other interrupts from being
 ; serviced until this routine is finished.
    SETB DDRB,Z80WAIT ;set Z80WAIT pin to output
    SKBC UART_I,PORTB ;skip next if UART interrupted us
    rjmp INT0_int_out ;false trigger, return to caller

; dummy processing to simulate operation
    push temp
    GoSub Delay5uS ;delay a little
    pop temp

    CLRB DDRB,Z80WAIT ;set Z80WAIT pin to output
    reti ;return to caller

Using the logic analyzer, I can clearly see that the interrupt latency is too great to be of any use at 1.5MHz to 8MHz Z80 clock speed. It does function correctly at 1MHz though but 1MHz is below the 2.5MHz clock speed rating of the Z80 when it was first released in 1976.

With the logic analyzer, I measured a interrupt response latency of 880nS at 1MHz Z80 clock speed. That’s 14 clock cycles on average, which is 4 cycles more than I had calculated but the AVR datasheet states there is a minimum of 5 clock cycles just to respond to a hardware interrupt, so the empiracle data correlates to the theoretical data.

If I use a simple “tight loop” structure to monitor the INTF0 flag in the EIFR register, there is still a 200 to 250nS response latency, so using the AVR to respond to a UART or DISK request in software is not possible.

Main1z:   ; for polling the INTF0 flag
 sbic   EIFR,INTF0         ;skip next if INTF0 is set
 rjmp   Main1z             ;continuously loop
 sbi    DDRB,Z80WAIT       ;set Z80WAIT pin to output
 call   ServiceRoutine     ;service the I/O request
 rjmp   Main1z             ;continue looping


AVR’s interrupt response latency. Z80 clock is 1MHz

Since I need to use the AVR for the SD memory “disk emulation”, I have to figure out a way to be able to make this method work. When the GAL22V10D SPLD’s come in, I will concentrate on the wait-state generator again as the only solution I see to proper operation is a hybrid software wait-state generation with hardware augmentation to buy the AVR time to take control of the WAIT line.

Next up, 1st attempt at a programmable wait-state generator.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s