I have two PIC18F4620 connected via SPI + Slave Select + additional IRQ line. Both controllers are driven from the same crystal oscillator using the same clock settings. The master sends one byte and then waits until the slave toggles that additional IRQ line. The duration of the toggling is 4 instruction cycles. All the edges look good on the scope and SPI communication works properly, except for the detection of the toggling (while(!PORTBbits.RB1);
).
This is my SPI sending code:
while (spi_out_msg_buffer.write_cursor > spi_out_msg_buffer.read_cursor)
{
DisableInterrupts;
SSPBUF = spi_out_msg_buffer.data[spi_out_msg_buffer.read_cursor];
LATBbits.LATB0 = 1;
while(!PORTBbits.RB1); // wait for toggle on IRQ line
LATBbits.LATB0 = 0;
EnableInterrupts;
spi_out_msg_buffer.read_cursor++;
}
The while(!PORTBbits.RB1);
is translated into two instructions:
BTFSS PORTB, 1, ACCESS
BRA 0x188
I insterted that B0
line for debugging purposes, you can see it at the very bottom of this timing diagram:
You can see the toggling of the IRQ line (second from the bottom) and how it goes undetected, because the B0
debugging line stays high. When I stop the execution via ICD it hangs inside the while
.
It is worth to mention that it usually works for a few bytes and then stops, as you can see here:
I measured that the pulse is actually 4 instruction cycles (= 16 PLL cycles = 4 clock cycles) long:
I think that should be sufficient for the pulse to be detected. Even if the first BTFSS misses it because the port is sampled at the beginning of the instruction cycle, then the second one should get it:
10 MHz -> PLL -> 40 MHz -> 10 M instructions per second -> 100 ns per instruction.
Shouldn't that be long enough to exit the while
?