11
\$\begingroup\$

I have a need to install an Arduino (actually just the IC) into existing hardware to enhance functionality.

What I would like to do is connect the Arduino so that it "spys" on the I/O lines between two chips on a board. If the Arduino picks up a specific keyword on that UART connection, it will perform a specific action on a separate set of output pins.

What I'm uncertain about is how to connect the Arduino in such a way that it can decode an existing UART connection without participating? If not possible, I am interested in theories, ideas, etc.

\$\endgroup\$
17
\$\begingroup\$

If I understand correctly you have 2 devices connected via UART. I assume just TX, RX and GND lines connected between the devices? (i.e., no DTS/CTS/DTR/RTS control lines used - this is typical).

In this scenario, device 1's TX (transmit) is connected to device 2's RX (receive), and vice-versa. Their grounds are connected to each other. Thus, each device can be transmitting and receiving at the same time (each transmits on a separate wire, the communication is full-duplex).

The reason I mention all this is because it becomes clear that to "sniff" or "listen", you'll actually need 2 UARTs to listen to both sides of the conversation.

Basically, all you'd do is ensure that all 3 devices' UART GNDs are shorted, and connect (really, "tee", as in a T-fitting, like plumbing) device 1 & device 2's TX lines to the 2 RX lines on 2 UARTs. Make sure that the baud rates are all configured identically.

There are a lot of Arduino boards / designs. The most common one nowadays, the Duemilanove, uses the ATMega328P, which I think has only 1 UART (well, USART). So you'd either have to wire up a 2nd UART IC, or resort to "bit banging" on the second receiver.

Async UART communications is well-defined, with start & stop bits (and sometimes parity bits), so if your processor is fast enough, you can simply connect one of the device's UART TX lines to a GPIO configured as input, and poll the line fast enough with oversampling to detect START & STOP and sample bits. The article "Bit Banging" by Jack Ganssle will give you plenty to chew on.

A decent description of the RS232 waveform can be found at BeyondLogic.

Note that there are other issues such as voltage levels (0/+5, -10V/+10V, etc.) that you'll have to take into consideration (see the Beyond Logic section on "RS232 Level Converters"). I don't have enough information on your system to discuss hardware interfacing besides the "connect the lines" approach discussed above. Assuming voltage levels are matched, usually it's not a problem to "tee" the TX line into a second receiver (the sniffer), but if the TX doesn't have enough drive, you might need to insert a buffer/driver to prevent the signal from degrading.

\$\endgroup\$
  • \$\begingroup\$ Beautiful! I will only need the data travelling in one direction so the single UART on the ATMega chip is just enough! The two chips communicate with +/-5V UART, which I think is the same as the ATMega. Wow, that should be it! Thanks! \$\endgroup\$ – Brad Hein Aug 4 '10 at 23:01
  • \$\begingroup\$ @BradHein, what you're calling "+/-5V" is usually referred to as "TTL level" - see en.wikipedia.org/wiki/Logic_level. \$\endgroup\$ – Mels Aug 6 '13 at 6:54
  • 3
    \$\begingroup\$ @Mels +/-5V is NOT TTL, TTL does NOT go below Ground. This is RS-232. \$\endgroup\$ – nmz787 Nov 2 '14 at 0:45
9
\$\begingroup\$

There's a neat trick you can do if the communication is in one direction only at a time (i.e. half-duplex communication). It won't work if both sides talk to each other at the same time (full duplex) but if it's your typical "do this" "ok here's the response" "now do this" "ok here's the new response" type of communications it works quite well.

Since the UART link uses an idle condition of the transmitter at a logic high (1) level you would use a 2-input AND gate and connect the TX from each side to an AND input. The output of the AND gate is your input to your sniffer's UART (it's RX pin). Now take device B's TX line and also bring it to an I/O port on the sniffer. You will configure the sniffer to generate an interrupt when this pin goes from high to low.

To recap: device A UART TX -> AND gate input. Device B UART TX -> other AND gate input AND sniffer GPIO pin. Output of AND gate -> sniffer UART RX line.

UART communications consist of a start bit, some number of data bits, an optional parity bit, and one or more stop bits. Since the idle state is a logic high (1), the start of EVERY byte will be a logic low (0) and the interrupt on the sniffer will fire. While your sniffer is executing the I/O interrupt the UART hardware will be collecting bits from the AND gate. By the time the UART has received the stop bit, the I/O interrupt will be long done and the UART RX interrupt will fire.

The interrupt-on-IO-change routine will set a "direction" variable to indicate that communications are in the "B->A" direction. The sniffer's UART receive interrupt would look at this "direction" variable and write the just-received byte to the appropriate buffer. The UART RX interrupt would then set the "direction" variable back to the default "A->B" state:

volatile int direction = 0;           /* 0 = A -> B */

void io_interrupt(void)
{
    direction = 1;                    /* switch direction, now B -> A */
}

void uart_interrupt(void)
{
    unsigned char b;

    b = UART_RX_REG;
    if(direction) {
        store_byte_to_device_b_sniff_buffer(b);
    } else {
        store_byte_to_device_a_sniff_buffer(b);
    }

    direction = 0;                   /* reset direction to default A -> B */
}

This code is written for clarity and not necessarily what you'd write in a real-world situation. Personally I'd make "direction" a pointer to the appropriate FIFO structure, but that's another exercise entirely. :-)

When device A is talking the I/O line does not move (it remains at a logic '1' since device B's UART transmitter is idle), and the UART RX interrupt will receive a byte, see that the direction is A->B, and store the data to that buffer. When device B is talking the I/O line will go low as soon as device B starts shifting data out, and the I/O interrupt routine will set the direction to indicate that device B is talking. The UART RX interrupt will eventually fire after all the bits have been collected and since I/O interrupt has taken care of setting the direction register appropriately, the received byte will be stored in the correct buffer.

Presto: half-duplex communications between two devices captured with a single UART and I/O line on the sniffer, with no bit-banged UART communications.

\$\endgroup\$
  • \$\begingroup\$ Intriguing. This is pushing the limits of my understandings, but it's great! One part I don't understand is how the sniffer's UART is connected to the target so that it can intercept both directions of communication? I have several I/O Pins available, so could I just use two I/O Pins using this method and effectively collect both directions of traffic? \$\endgroup\$ – Brad Hein Aug 5 '10 at 11:52
  • \$\begingroup\$ The sniffer UART RX line is connected to the output of the AND gate. Device A's UART TX is connected to one input of the AND gate, and device B's UART TX is connected to the other input of the AND gate. Since the idle (no traffic) condition of a UART is a logic '1', the AND gate effectively combines both transmit signals into one. The I/O line on the sniffer is used to detect device B's start bit so that it can take the byte it is receiving on its UART and put it in the appropriate buffer (device A traffic or device B traffic). \$\endgroup\$ – akohlsmith Aug 5 '10 at 19:06
  • \$\begingroup\$ The code fragment and the wiring of the AND gate allow the sniffer to record both directions of traffic flow with a single UART. This ONLY works if the traffic is half-duplex. That means that when one device is talking, the other is listening. If both talk at the same time (full duplex) then this would not work at all. \$\endgroup\$ – akohlsmith Aug 5 '10 at 19:07
5
\$\begingroup\$

You don't have to hook the AVR's transmit-data pin into your circuit. Just connect the receive line to the half of the the existing link you want to eavesdrop on. If your particular AVR has two serial ports, you should be able to spy on both halves of the existing link simultaneously. You just have to make the port settings match the existing baud rate, stop bits, etc.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.