Saturday, April 21, 2018
Many modern AVRs have an on-chip one-wire debugger called debugWire that uses the RESET pin when the DWEN fuse is programmed. The AVR manuals provide no details on the protocol, and the physical layer description is rather terse: "a wire-AND (open-drain) bi-directional I/O pin with pull-up enabled". While much of the protocol has been reverse-engineered, my initial experiments with debugWIRE on an ATtiny13 were unreliable. Suspecting possible issues at the physical layer, I got out my scope to do some measurements.
I started with a single diode as recommended by David Brown. I used a terminal program to send a break to the AVR, which responds with 0x55 about 150us after the break. As can be seen in the scope image above, the rise time can be rather slow, especially with Schottky diodes since they have much higher capacitance than standard diodes like a 1N4148. Instead of a diode, Matti Virkkunen recommends a 1K resistor for debugWIRE. For UPDI, which looks like an updated version of debugWire, a 4.7K resistor is recommended. I ended up doing a number of tests with different resistor values, as well as tests with a few transistor-based circuits. While the best results were with a 2N3904 and a 47K pull-up to Vcc on the base, I achieved quite satisfactory results with a 1.4K resistor:
The Tx low signal from both the Pl2303 and the AVR are slightly below 500mV, which both sides consistently detect as a logic level 0. With 3.5Vcc, I found that levels above 700mV were not consistently detected as 0. As can be seen from the scope image, the signal rise time is excellent. The Tx low from the Pl2303 is slightly lower than the Tx low from the AVR, so a 1.5K resistor would likely be optimal instead of 1.4K.
You might notice in the scope image that there are two zero frames before the 0x55 response from the AVR. The first is a short break sent to the AVR, and the second is the break that the AVR sends before the 0x55. While some define a break as a low signal that lasts at least two frame times, the break sent by the AVR is 10 bit-times. Since debugWire uses 81N, a transmitted zero will be low for 8 bits plus the start bit before going high for the stop bit. That means the longest valid frame will be low for 9 bit-times, and anything more than 10 bit-times low can be assumed to be a break. Another thing I discovered was that the AVR does not require a break to enter dW mode after power-up. A zero frame (low for 9 bit-times) is more than enough to activate dW mode, stopping the execution on the target. Once in dW mode, a subsequent zero frame will cause the target to continue running, while continuing to wait for additional commands.
My results with a 1.4K resistor are specific to the ATtiny13 + Pl2303 combination I am using. A different USB-TTL dongle such as a CP2102 or CH340G could have different Tx output impedance, so a different resistor value may be better. A more universal method would be to use the following basic transistor circuit:
One caveat to be aware of when experimenting with debugWIRE is that depending on your OS and drivers, you may not be able to use custom baud rates. For example under Windows 7, I could not get my PL2303 adapters to use a custom baud rate. Under Linux, after confirming from the driver source that custom baud rates are supported, I was eventually able to set the port to the ~71kbps baud rate I needed to communicate with my tiny13. That adventure is probably worthy of another blog post. For a sample of what I'll be discussing, you can look at my initial attempt at a utility to detect the dW baud rate of a target AVR.