I C Bus Sniffer: Entry Documentation A3808
I C Bus Sniffer: Entry Documentation A3808
I C Bus Sniffer: Entry Documentation A3808
Introduction
The I2C Bus Sniffer allows for non-intrusive monitoring of an I2C bus. All data, including device addresses, ACK/NAK, START and STOP conditions, are reported in textual form to a serial terminal. A familiar theme in open-source projects is a need to scratch an itch. In my case, the itch was a need to know exactly what was happening on an I2C bus on a certain system at work. Commercial products are available, but the immediate cost (versus engineering time, which is a cost spread over time) was too high to justify it. In the end, I hooked up a logic analyzer, captured the SCL and SDA lines, and the deciphered the protocol by hand. That fixed the immediate problem, but I didn want to do that again, and I resolved t to create my own I2C bus monitor in my spare time. The I2C bus was developed by Philips in the 1980 It is a serial bus, consisting of a clock and data line. s. The protocol specifies START and STOP conditions, the data format (8 bits, MSB first), and and ACK/NAK bit. Refer to [1] for the complete specification. Aside from minimum widths, the clock pulses do not have to be of the same width, which makes the bus quite flexible for implementation on even the smallest microcontrollers.
ground or Vcc, or even something as simple as a memory chip entirely missing. The memory test code, while interesting in its own right, is here merely a means to an end, and will not be discussed further. On the hardware side, I had initially planned what is now called the grandiose vision, which was a small, self-contained unit that would attach to any system I needed to monitor. Certain options would be available for dropping down to 9600 baud (where the 32KB of external buffer would be even more important) when I was connected to a [very] dumb terminal, as well as utilizing RTS/CTS flow control. Even better, I planned to use opto-isolators to further protect the Unit Under Test from the bus monitor, and vice-versa. I drew the schematic, laid out the PCB, assembled it (ref. A3808_pic_the_grandiose_vision.jpg), and nothing worked. Yes, I am aware that the resistor color codes in the JPG do not match the silkscreen designations; I was experimenting with different resistor values. The lesson to learn here is first, the prototype. I took a second PCB (the fab house sent me 3) and cut it down to just the microcontroller, latch, and SRAM. This is the subset version of the hardware. If I had an STK501, this wouldn have been t necessary, but I don have an STK501, and so I needed a way to hook up the external SRAM (ref. t A3808_pic_on_stk500.jpg). With the subset hardware on the STK500, I was able to focus on the software instead of worrying about the hardware. All of the heavy work is done inside ISR An I2C bus START or STOP condition consists of the SDA s. signal changing when SCL is high, so I wrote an ISR to be called on either edge of SDA. On entry, it tests SCL. If it is low, the ISR exits immediately. Otherwise, the new level of SDA determines if we have just seen a START or STOP condition. The condition is recorded in RAM (S for START, P for STOP, as per the common usage I have seen in other documents), bit counters are reset, and we exit. The interrupt for SCL (to capture data bits) is enabled after seeing a START condition, and disabled after seeing a STOP condition. To capture data bits, I only need the rising edge of SCL. Each interrupt, I sample the SDA pin to see if I have a 1 or 0 bit. The bit is rotated into a register designated for capturing the data, and the bit count is incremented. Once I have 8 bits, I convert to ASCII and store in RAM. The next bit will be an ACK or NAK, which I capture and store in RAM as an A or N. Storing data in RAM is done in a subroutine so I can check to make sure we haven walked off the end of 32KB. If so, we reset to the beginning of t external RAM and continue. Once completed, the subset hardware on an STK500 was perched atop a CompactPCI chassis (ref. A3808_pic_atop_cpci_chassis.jpg) and connected to the unit under test with jumper wires (ref. A3808_pic_connected_to_unit_under_test.jpg). I powered on the STK500, observed the memory test results (pass), and then powered on the unit under test. Here is a sample of the output from the bus sniffer, as it monitors the aforementioned unit under test: S C0 A 73 A E2 A 05 A 00 A 00 A P S C0 A 00 A 7F A 5F A 55 A 00 A P S C0 A 02 A 1F A 07 A 99 A A0 A P S C0 A 5C A 00 A 00 A 00 A D8 A P S C0 A 78 A 00 A 80 A 10 A CC A P S C0 A 7B A E0 A 05 A 00 A 00 A P S A0 A 00 A S A1 A 31 A 31 A 31 A 31 A 31 A 31 A 31 A 31 N P S C0 A 21 A 00 A 00 A 05 A 58 A P S C0 A 21 A S C1 A 00 A 00 A 00 A 80 N P The unit writes to registers on the device at address 0xC0, reads data from the EEPROM at address 0xA0 (note the Repeated Start condition, followed by address 0xA1), writes again to 0xC0, and then reads (again, a Repeated Start) from 0xC1. After I got all the kinks out of the software, I went back to my full PCB and found a few problems. The worst was the opto-isolators for the SDA and SCL signals. Depending on the values of the resistors, I wound up either pulling the SDA and SCL signals too low on the unit under test (thereby hanging the bus),
or the signal passing through the opto-isolator was too weak to register as a high on the AVR. I have to ll revisit the isolator design at some point in the future. Until then, I can simply jumper across the resistor posts and forego the opto-isolation. The AVR must process several instructions for each bit on the I2C bus. This limits the maximum bus speed that can be reliably monitored to 100 KHz. Anything beyond that will require extra logic to capture the serial stream and present it to the microcontroller for further processing. This could be an interesting future project for an FPSLIC. The current revision of the software simply displays all data received. Future software will focus on the following: ? RTS/CTS flow control ? address filtering: capture only when address XX is used ? delayed report: the sniffer will capture the data, but not print it until specifically instructed, with the option to page through the data, back up a page, and so on Future hardware work will focus on fixing the opto-isolator circuit, as well as the possibility of adding programmable logic to allow monitoring high-speed I2C busses.
Block Diagram
RS-232
ATMEGA161
SRAM
SCL SDA
INT0 INT1
This has to be one of the most boring block diagrams I ever drawn. The microcontroller uses external ve RAM, an RS-232 port, and two inputs. The Grandiose Vision does not add much complexity; SCL and SDA are opto-isolated, jumpers are present for software options (force to 9600 baud), and the RS-232 interface can use RTS/CTS flow control.
References
[1] Philips I2C bus specification, http://www.semiconductors.philips.com/acrobat/literature/9398/39340011.pdf [2] Applied Cryptography, 2nd Edition, Bruce Schneier, pp. 372-379