All You Ever Needed To Know About UPDI, And Then Some!

This entry is part 1 of 1 in the series IMPLEMENTING UPDI FROM SCRATCH

IMPLEMENTING UPDI FROM SCRATCH

All You Ever Needed To Know About UPDI, And Then Some!

All You Ever Needed To Know About UPDI, And Then Some!

Post Stastics

  • This post has 6586 words.
  • Estimated read time is 31.36 minute(s).

Table of Contents

Part I — Foundations, Electrical Interface, Protocol, and High-Voltage Activation

There was a time when connecting a programmer to an AVR microcontroller could consume a surprisingly large number of pins. Traditional AVR In-System Programming used SPI-like signaling. JTAG used four principal signaling wires plus reset and power references. debugWIRE reduced debugging to essentially one signal, but came with its own peculiarities. The XMEGA family introduced PDI.

Modern AVR microcontrollers took the idea considerably further.

For many of Microchip’s current AVR devices, programming, fuse access, memory inspection, chip erase, and on-chip debugging can all be reached through one signal wire.

That interface is called:

UPDI — Unified Program and Debug Interface

Do not let the single wire fool you.

Behind that pin lies a surprisingly complete communications system containing:

  • a UART-like physical layer;
  • synchronization and collision handling;
  • an instruction protocol;
  • address-space access mechanisms;
  • protected activation keys;
  • nonvolatile-memory controllers;
  • an on-chip debug system;
  • and, on some devices, a special high-voltage activation mechanism capable of recovering a device whose normal UPDI pin function has been disabled.

The goal of this article is not merely to tell you how to connect an existing programmer.

We are going considerably farther.

By the end of this series we will understand UPDI well enough to build a working programmer around an ordinary ATmega328P Arduino Nano, communicate with real modern AVR devices, read and write their memory, erase them, manipulate fuses safely, add externally generated high-voltage UPDI activation, and examine the architecture needed to extend our implementation into a useful on-chip debugger.

The example hardware deliberately remains accessible to the hobbyist:

  • an ordinary 5 V, 16 MHz Arduino Nano based on the ATmega328P;
  • Arduino IDE as the development environment and toolchain;
  • a handful of inexpensive resistors, diodes, and small-signal transistors;
  • a target AVR supporting UPDI;
  • and, for high-voltage experiments, an external current-limited bench power supply rather than an onboard high-voltage converter.

The finalized reference hardware also provides:

  • target-voltage sensing;
  • high-voltage sensing;
  • independent target reset control;
  • separately switched and routable high voltage;
  • an optional target-power control output;
  • and a transistor-translated UPDI interface that keeps the Nano’s 5 V GPIO pins electrically separated from the target voltage domain.

The completed article schematic implements those functions around an Arduino Nano while still presenting the target with the normal four useful development connections: RESET, VTARGET, UPDI, and GND.

The design will nevertheless be approached as an engineer should approach it:

By understanding what every wire, byte, timing interval, fuse, transistor, resistor, and voltage actually does.


1. What Is UPDI?

UPDI stands for:

Unified Program and Debug Interface

Microchip describes it as a proprietary interface intended for external programming and on-chip debugging of AVR microcontrollers.

It succeeds the two-wire PDI physical interface used by the AVR XMEGA family.

UPDI reduces that connection to a:

  • bidirectional;
  • half-duplex;
  • asynchronous;
  • one-wire

communications interface.

That sentence contains several important ideas.

Bidirectional

Information travels both:

programmer → target

and:

target → programmer

over the same physical UPDI conductor.

Half duplex

Both ends use the same communication line, but they do not normally transmit simultaneously.

At any given moment:

programmer transmits

or:

target transmits

or:

line is released

but both sides should not intentionally drive conflicting states at the same time.

Asynchronous

There is no separate clock wire.

Timing is recovered from the serial data stream.

UART-like

At the physical level, UPDI deliberately resembles ordinary asynchronous serial communication.

More than a programming interface

The same physical connection reaches both:

programming resources

and:

on-chip debugging resources

on applicable devices.

A conceptual minimum connection can consequently be as simple as:

PROGRAMMER                         TARGET AVR
+-----------+                      +-----------+
|           |                      |           |
|      UPDI |----------------------| UPDI      |
|           |                      |           |
|       GND |----------------------| GND       |
|           |                      |           |
+-----------+                      +-----------+

Frequently we also want:

VTARGET / VDD

as a voltage reference or power connection.

That is the attraction of UPDI from a PCB designer’s perspective.

A production board may require only a tiny number of programming contacts.

This makes UPDI especially attractive for:

  • production test pads;
  • pogo-pin programming fixtures;
  • hobby boards;
  • small embedded systems;
  • factory programming;
  • bootstrapping new boards;
  • debugging assembled hardware;
  • designs where connector area is scarce.

But UPDI’s simplicity exists primarily at the connector.

The protocol behind that connector is considerably richer.


2. Where UPDI Fits in AVR History

AVR programming interfaces have evolved considerably.

Classic AVR devices commonly used SPI-based ISP programming.

Larger devices frequently provided JTAG.

debugWIRE allowed debugging through RESET on many smaller classic AVR devices.

XMEGA introduced PDI.

UPDI is the next major simplification of that concept.

Microchip identifies UPDI as the successor to XMEGA’s PDI physical interface.

Today UPDI appears throughout several generations of the modern AVR architecture, including members of:

  • tinyAVR 0-series;
  • tinyAVR 1-series;
  • tinyAVR 2-series;
  • megaAVR 0-series;
  • AVR DA;
  • AVR DB;
  • AVR DD;
  • AVR DU;
  • and additional newer AVR families.

There is, however, an extremely important engineering warning:

UPDI compatibility does not mean that every UPDI AVR uses the same Flash-programming procedure.

The UPDI communications mechanism is only one part of programming the microcontroller.

UPDI gives us a way to access internal resources.

Actual Flash and EEPROM programming is performed through the target’s:

Nonvolatile Memory Controller — NVMCTRL

Microchip has changed that controller architecture across device generations.

Therefore:

UPDI physical/link protocol
           |
           v
memory/register access
           |
           v
target-specific NVM controller
           |
           v
Flash / EEPROM / fuses / USERROW

A programmer may understand UPDI communications perfectly and still fail to program a newer device if it does not understand that device’s NVM controller.

This distinction will become particularly important when we design our Nano firmware.

It is also visible in existing open-source implementations.

Different modern programmers contain separate NVM backends precisely because the same UPDI link may sit in front of different NVM-controller generations.

Throughout this article we will therefore keep three concepts separate:

UPDI communications

UPDI programming-mode activation

device-family-specific NVM programming

That separation makes both the protocol and our eventual software architecture much easier to understand.


3. UPDI Is Really Several Layers

The easiest way to understand UPDI is to stop thinking of it as a magic programming wire.

Think of it instead as a small communications stack.

Conceptually:

+--------------------------------------------------+
| Host software                                    |
| Arduino IDE / programmer utility / debugger      |
+--------------------------------------------------+
                       |
+--------------------------------------------------+
| Programmer command protocol                      |
| Our protocol / serial commands / GDB RSP etc.    |
+--------------------------------------------------+
                       |
+--------------------------------------------------+
| Programming / debugging algorithm                |
| NVMCTRL operations, keys, erase, OCD control     |
+--------------------------------------------------+
                       |
+--------------------------------------------------+
| UPDI instruction layer                           |
| LDS STS LD ST LDCS STCS REPEAT KEY               |
+--------------------------------------------------+
                       |
+--------------------------------------------------+
| UPDI serial/data-link layer                      |
| SYNCH, ACK, BREAK, framing, turnaround           |
+--------------------------------------------------+
                       |
+--------------------------------------------------+
| Electrical physical layer                        |
| Single bidirectional target signal + ground      |
+--------------------------------------------------+

This distinction becomes extremely useful when debugging our own programmer.

For example:

If the waveform has the wrong parity:

physical/serial-layer problem

If LDCS returns nonsense:

instruction framing,
synchronization,
or receive problem

If register reads work but Flash writes fail:

UPDI may be completely functional;
the problem may be the NVM algorithm

If programming works from our console but AVRDUDE cannot use our programmer:

host-to-programmer protocol problem

That is why statements such as:

“AVRDUDE speaks UPDI”

can sometimes obscure what is actually happening.

There may be several separate communications links involved.


4. The Physical Connection

The ordinary target-side UPDI connection is refreshingly small.

At minimum:

PROGRAMMER                        TARGET
GND  --------------------------- GND
UPDI --------------------------- UPDI

In most practical systems we also want access to the target supply voltage:

PROGRAMMER                        TARGET
GND      ----------------------- GND
UPDI     ----------------------- UPDI
VTARGET  ----------------------- VDD

VTARGET may serve several different purposes.

A programmer may:

  • supply target power;
  • merely measure target voltage;
  • use target voltage as a logic-domain reference;
  • verify that a target is actually powered;
  • or use it when selecting a safe programming/HV mode.

Our final Nano design primarily treats VTARGET as:

target-voltage sense
+
target logic-domain reference

although an optional power-control circuit is also provided.

For a more complete development connection, we also expose RESET:

PROGRAMMER                        TARGET
RESET    ----------------------- RESET
VTARGET  ----------------------- VDD
UPDI     ----------------------- UPDI
GND      ----------------------- GND

Our reference target connector therefore uses four useful signals:

1  RESET
2  VTARGET
3  UPDI
4  GND

RESET is not required for ordinary UPDI communication on every AVR.

We expose it because:

  • ordinary target reset is useful;
  • automated test systems may need it;
  • debugging may benefit from independent reset control;
  • and some newer AVR devices use a separate RESET pin for high-voltage UPDI activation.

The communication interface itself remains:

one-wire UPDI.


5. One External Wire, Separate Internal TX and RX

Because UPDI is half duplex, programmer and target share one physical data conductor.

At some moments the programmer drives the line.

At other moments the target drives it.

At still other moments neither side should actively pull it LOW.

Conceptually:

             programmer transmits
                    |
                    v

HIGH  ----+    +----+       +----
          |    |
LOW       +----+

             programmer releases
                    |
                    v

HIGH  ----------------+     +-----
                       |     |
LOW                    +-----+
                       ^
                       |
                  target transmits

A very simple Arduino implementation can connect one GPIO to UPDI through a resistor and repeatedly change that GPIO between output and input states.

That approach is practical and has been demonstrated by projects such as jtag2updi.

Our final article hardware uses a somewhat more capable arrangement.

Externally there is still only one UPDI conductor.

Internally we split it into:

UPDI_TX

and:

UPDI_RX

using two inexpensive transistors.

Conceptually:

Nano D6 / UPDI_TX
        |
        v
 open-collector TX
        |
        +-------------------+
                            |
                         TARGET
                          UPDI
                            |
        +-------------------+
        |
        v
 transistor RX
        |
Nano D5 / UPDI_RX

This provides several useful advantages:

  • the Nano never directly drives a 5 V HIGH into the target;
  • target HIGH levels remain referenced to the target voltage domain;
  • lower target voltages are easier to accommodate;
  • the receive path returns a normal Nano-domain logic signal;
  • Nano GPIO pins are isolated from an older 12 V UPDI activation pulse;
  • TX and RX timing are easier to reason about;
  • and RX can remain active while TX is operating, allowing useful echo/line-state checks.

This is a very important distinction:

UPDI remains one wire externally.
The two-GPIO arrangement exists only inside our programmer.


6. UPDI’s UART-Like Frame

UPDI uses a fixed asynchronous DATA frame.

Microchip specifies:

1 start bit
8 data bits
1 even-parity bit
2 stop bits

In conventional UART notation:

8E2

That means:

8 data bits
Even parity
2 stop bits

Graphically:

Idle  Start       Data bits              Parity  Stop Stop

HIGH    LOW    D0 D1 D2 D3 D4 D5 D6 D7    P      1    1
----+       +--+--+--+--+--+--+--+--+----+----+------>
    |       |
    +-------+

The data bits are transferred least-significant bit first.

The second stop bit is useful on a half-duplex link because it provides additional settling and turnaround time.


7. Why Even Parity?

Parity provides a simple error-detection mechanism.

With even parity, the parity bit is chosen so that the total number of logical ones among:

D0 ... D7 + parity

is even.

For:

00000001

the data contains one logical 1, so parity must also be 1.

Total ones:

2

which is even.

For:

00000011

the data already contains two logical ones.

Parity is therefore:

0

Parity cannot detect every possible transmission error, but it detects many common single-bit errors essentially for free.

Our implementation will generate and check correct parity rather than depending on any optional parity-disable mechanism.


8. UPDI Does Not Use a Fixed Baud Rate in the Ordinary UART Sense

One of UPDI’s clever features is automatic baud synchronization.

The target does not simply assume:

9600
19200
115200
225000

or another permanently fixed rate.

Instead, before each new UPDI instruction, the programmer sends:

0x55

as a synchronization character.

Why 0x55?

Binary:

01010101

This produces a highly regular alternating edge pattern:

0 1 0 1 0 1 0 1

which is ideal for measuring bit timing.

The target observes this pattern and adjusts its serial timing.

Therefore a normal instruction begins conceptually with:

55  instruction operands...
^^
SYNCH

This property is particularly useful for a homemade programmer because the target repeatedly receives opportunities to synchronize itself to our transmitter.


9. Important UPDI Frame Types

Besides ordinary DATA frames, UPDI defines several important special conditions or frames:

IDLE
BREAK
SYNCH
ACK

Understanding these mechanisms is essential before we begin writing firmware.


10. IDLE

An idle UPDI line is HIGH.

An IDLE condition consists of the line remaining HIGH for at least the required number of bit periods.

Conceptually:

UPDI

HIGH  ------------------------------------

LOW

          sustained HIGH / released bus

The exact electrical source of that HIGH state depends on the target and programmer interface.

From the protocol perspective:

HIGH means idle.

Our open-collector transmitter therefore creates a HIGH state by:

turning its transistor OFF

and releasing the target line.


11. BREAK

BREAK is the opposite.

A UPDI BREAK holds the line LOW for an extended period.

At the basic frame level, BREAK may be understood as a LOW condition lasting at least the required number of bit periods.

Its role is extremely important.

BREAK resets UPDI’s communications state machine.

It is our primary recovery tool when:

  • synchronization has been lost;
  • a malformed packet was transmitted;
  • target and programmer disagree about transaction state;
  • an interrupted operation left UPDI waiting for more data.

Think of BREAK as:

“Forget what we were doing and return the communication interface to a known state.”

A double BREAK provides particularly robust recovery because the first BREAK can terminate an operation already in progress and the second can reset the newly receptive interface.


12. BREAK Timing Is More Subtle Than Twelve Ordinary Bits

If both ends already agree on the baud rate, expressing BREAK as a number of bit periods is straightforward.

But what happens if synchronization has been lost completely?

Microchip consequently documents conservative BREAK durations based on UPDI’s internal clock.

Representative documented recovery durations include approximately:

UPDI clock       recommended BREAK

16 MHz                 6.15 ms
 8 MHz                12.30 ms
 4 MHz                24.60 ms

For implementations whose default internal UPDI clock is around 4 MHz, approximately:

24.6 ms

is therefore a useful conservative recovery BREAK.

Compare that with twelve bit periods at 225 kbaud:

12 / 225000 ≈ 53.3 µs

Those are very different durations.

This is why our eventual firmware should distinguish between:

ordinary frame-level BREAK

and:

robust unknown-state recovery BREAK

rather than assuming one timing value is universally appropriate.


13. SYNCH

After recovery if required, and before every new UPDI instruction, comes:

0x55

A typical command therefore looks conceptually like:

BREAK       // when recovery is needed
0x55        // SYNCH
COMMAND
OPERANDS

Not every command needs a BREAK.

Every new UPDI instruction does need synchronization.


14. ACK

Some write operations require the target to tell the programmer:

“I accepted that operation and successfully obtained access.”

That response is:

ACK

ACK is especially associated with writes such as ST and STS when synchronization and bus-access conditions require confirmation.

This means our programmer cannot simply throw bytes onto UPDI as fast as its CPU can generate them.

The protocol contains real:

request
response
turnaround

behavior.

That brings us naturally to the UPDI instruction set.


15. The UPDI Instruction Set

UPDI has a pleasantly small core instruction vocabulary.

The principal instructions are:

LDS
STS
LD
ST
LDCS
STCS
REPEAT
KEY

Although eight instruction families may not sound like much, together they provide enough functionality to reach almost everything needed for programming and debugging.

Before worrying about binary opcode encoding, it is useful to understand what each instruction category means conceptually.


16. LDS — Load Direct from Data Space

LDS means approximately:

read data directly from a specified address

Conceptually:

value = memory[address]

Suppose we want to inspect a memory-mapped peripheral register.

LDS address
      |
      v
target address space
      |
      v
return byte/word

Because modern AVR peripherals and memories are extensively memory mapped, this apparently simple operation gives UPDI enormous reach.


17. STS — Store Direct to Data Space

STS is the complementary operation:

memory[address] = value

This allows the programmer to modify a directly addressed memory location.

That might be:

  • SRAM;
  • an I/O register;
  • an NVMCTRL register;
  • a fuse-related location where access is permitted;
  • or another memory-mapped resource.

When programming Flash, however, we generally do not merely issue a generic STS and expect a Flash cell to magically change.

Instead:

UPDI
   |
   v
NVMCTRL
   |
   v
Flash operation

The programmer must follow the target family’s NVM-controller procedure.

Again:

UPDI supplies access.
NVMCTRL performs the nonvolatile-memory operation.


18. LD and ST — Indirect Access

LD and ST use UPDI’s internal pointer mechanism.

Instead of repeatedly transmitting a complete address, we can establish a pointer and operate through it.

Conceptually:

pointer = 0x2000

LD pointer
pointer++

LD pointer
pointer++

LD pointer
pointer++

That becomes much more efficient when transferring sequential blocks of memory.


19. REPEAT — Efficient Block Transfers

The REPEAT instruction tells UPDI to repeat a following operation multiple times.

Combined with pointer-based LD/ST access:

set pointer = buffer_start

REPEAT count
ST pointer++, data

can transfer a sequential block with much less protocol overhead.

The exact count semantics and supported transfer widths must be implemented according to the relevant UPDI documentation.

The architectural purpose is straightforward:

REPEAT makes sequential memory transfers efficient.

That becomes very important when programming Flash or reading blocks of data.


20. LDCS and STCS — UPDI’s Own Control Registers

UPDI contains its own internal control/status register space.

This is distinct from ordinary target memory.

LDCS means:

Load Control/Status

and STCS means:

Store Control/Status

These registers contain information associated with such things as:

  • UPDI status;
  • control configuration;
  • reset requests;
  • error state;
  • system/interface status.

An excellent early milestone for our Arduino programmer is therefore:

generate BREAK
send SYNCH
issue LDCS
receive a known value

If that works reliably, then we know that:

  • the electrical connection works;
  • TX works;
  • RX works;
  • timing works;
  • inversion handling works;
  • parity works;
  • stop bits work;
  • SYNCH works;
  • and target-to-programmer communication works.

That is a much better first experiment than immediately attempting chip erase.


21. KEY — Opening Protected Doors

The KEY instruction is particularly interesting.

Some sensitive UPDI operations are not enabled merely because the programmer has electrical access.

UPDI uses specific keys to activate protected functions.

These include operations associated with:

  • NVM programming;
  • chip erase;
  • USERROW access on applicable devices;
  • and other protected modes.

This is not encryption.

It is better thought of as a protocol-level authorization or intent mechanism.

Conceptually the target requires the programmer to say:

“I deliberately request access to this protected subsystem.”

before the operation becomes available.

KEY becomes especially important when we discuss high-voltage activation.


22. UPDI and the AVR Memory Map

One of UPDI’s most powerful architectural characteristics is its ability to reach the AVR address space.

Applicable UPDI debugging capabilities include access to:

NVM
RAM
I/O space

This means the same fundamental communication mechanism participates in both programming and debugging.

For programming:

UPDI
  |
  +--> NVMCTRL
  |
  +--> Flash
  |
  +--> EEPROM
  |
  +--> fuses

For debugging:

UPDI
  |
  +--> SRAM
  |
  +--> peripheral registers
  |
  +--> OCD resources
  |
  +--> CPU state

Applicable devices also provide OCD capabilities involving:

  • program flow control;
  • PC/SP/SREG observation;
  • breakpoint handling;
  • register access;
  • runtime monitoring.

This is why the word:

Unified

in UPDI is meaningful.

Programming and debugging no longer require separate physical interfaces.


23. What Happens When a Device Is Locked?

Security changes what UPDI is permitted to see.

If a locked device allowed unrestricted reads of program memory, its protection mechanism would be meaningless.

On applicable locked AVR devices, ordinary UPDI access to protected system resources is restricted.

UPDI itself may remain capable of communicating with:

its own control/status areas
+
the asynchronous system interface

so that the programmer can determine target state and perform permitted recovery operations.

Conceptually:

UNLOCKED:

UPDI ---> system bus ---> memory/peripherals


LOCKED:

UPDI -X-> protected system bus
  |
  +-----> permitted UPDI/ASI functions

This distinction is important when troubleshooting.

A programmer that communicates correctly with UPDI but cannot read protected Flash may be operating exactly as intended.

The target may simply be locked.


24. The Often-Misunderstood “High Voltage” in UPDI

Now we reach one of the most frequently misunderstood topics.

You will often hear:

“UPDI uses 12-volt programming.”

That statement is badly incomplete.

In UPDI, the high-voltage pulse is generally not the voltage used to physically program Flash memory.

Instead, high voltage is an:

interface activation mechanism.

Conceptually:

          HV activation
               |
               v
      +------------------+
      | Make UPDI        |
      | accessible       |
      +------------------+
               |
               v
          normal UPDI
               |
               v
      ordinary NVM control

Once UPDI has been activated, normal digital UPDI signaling performs the communications.

High voltage does not become a Flash programming supply.


25. Why Is High-Voltage Activation Needed?

Some AVR packages have very few pins.

Dedicating one pin permanently to programming reduces the number available to the application.

Some AVR families therefore allow a shared pin to function as:

UPDI
RESET
GPIO

depending on configuration.

That is useful.

But it introduces an obvious problem.

Suppose the application configuration assigns that pin to GPIO.

How can the programmer recover UPDI access?

High-voltage activation provides a special override mechanism.

Conceptually:

configured GPIO/RESET
        |
        | special HV sequence
        v
temporary UPDI access

The exact mechanism depends on the AVR family.


26. Not Every UPDI Device Needs the Same High Voltage

This is one of the most important rules in the entire article.

There are several relevant physical arrangements.

Arrangement 1 — Shared UPDI/RESET/GPIO

This arrangement appears on a number of small devices.

Recovering UPDI access may require approximately:

12 V

on the shared UPDI pin according to the target’s documented activation sequence.


Arrangement 2 — Dedicated UPDI

Other devices provide a dedicated UPDI pin.

If UPDI remains dedicated and physically available, the same high-voltage recovery mechanism is generally unnecessary.


Arrangement 3 — UPDI/GPIO with Separate RESET

Some newer AVR families provide UPDI/GPIO functionality together with a separate RESET pin.

In these devices, high-voltage activation may instead be applied to:

RESET

at a target-specific voltage.

Representative documented values for this class include approximately:

minimum:  VDD + 2 V
typical:  7.5 V
maximum:  8.5 V

subject always to the exact target’s electrical specifications and absolute maximum ratings.

This produces one of our strongest design rules:

Never assume that “UPDI HV” always means 12 V.

The voltage, destination pin, and timing depend on the target device.


27. What High Voltages Should Our Programmer Support?

Because our educational programmer uses an external bench supply, it can remain unusually flexible.

We will conceptually distinguish at least two high-voltage classes.

HV12

Approximately:

12 V

for applicable older shared-pin UPDI activation.

HVLOW / RESET-HV

Target-specific lower-voltage activation, commonly around:

VDD + 2 V

on applicable newer devices.

Before applying either one, the programmer should eventually know:

target identity
target VDD
HV activation class
HV destination pin
allowed HV range
required pulse timing

A mature programmer should obtain this information from a device database.

For our educational system, HV selection remains deliberately explicit.

The bench supply is set manually.

The programmer measures the HV rail.

A physical route/arm jumper determines where the switched HV is sent.

This is safer than assuming that one high-voltage mode applies universally.


28. Never Apply 12 V Blindly to “A UPDI Pin”

A programmer capable of producing 12 V is also capable of damaging hardware.

Anything electrically connected to a shared UPDI/HV node must either:

tolerate the activation voltage

or:

be isolated from it

Imagine:

                     +---------- target AVR
                     |
12 V pulse ----------+---------- logic buffer
                     |
                     +---------- LED
                     |
                     +---------- sensor IC

If those branches are not designed for 12 V, HV recovery may damage them.

This is why production hardware may use:

  • isolation;
  • series resistance;
  • transistor interfaces;
  • removable jumpers;
  • dedicated programming pads;
  • carefully designed buffers.

Our finalized Nano programmer specifically avoids connecting the Nano GPIO pins directly to the target UPDI conductor.

The target-side UPDI line instead reaches:

TX transistor collector
RX transistor through a resistor

while the Nano sees only its own 5 V logic domain.

Consequently an intentional older-style 12 V UPDI activation pulse does not appear directly on D5 or D6.

The optional external UPDI pull-up is also isolated from VTARGET through a series diode and is DNP by default.

That provides considerably better protection than a bare Nano GPIO connected through only a series resistor.


29. HV Activation Is a Pulse, Not a Programming Supply

High voltage is temporary.

Older shared-pin UPDI activation sequences use a pulse-like operation rather than continuous 12 V Flash programming.

A representative documented sequence uses a pulse on the order of:

100 µs to 1 ms

before the programming driver returns to a non-driving state.

Newer lower-voltage mechanisms have their own timing specifications.

Some document minimum HV durations around:

10 µs

with practical activation sequences recommending longer pulses.

Therefore our firmware will represent HV as:

target-specific operation

rather than:

digitalWrite(HV, HIGH);
delay(arbitrary_value);

with one universal delay.


30. The Approximately 65 Millisecond Window

High-voltage activation includes another useful safety mechanism.

An electrostatic-discharge event can produce a voltage transient far above the normal supply.

Without further confirmation, such an event could accidentally resemble an HV activation pulse.

Applicable UPDI implementations therefore require a valid activation key shortly after the HV event.

A representative documented interval is approximately:

65 ms

Conceptually:

                 HV pulse
                    |
                    v

time ---------------+----------------------------------->
                    |<--------- ~65 ms --------->|
                    |
                    +---- establish UPDI
                    |
                    +---- send valid KEY
                    |
                    +---- continue required sequence

If the required key is not supplied within the permitted interval, the target can treat the event as invalid or accidental.

That is considerably more sophisticated than:

“Apply 12 V and the chip enters programming mode.”


31. HV Activation Can Be Temporary

High-voltage activation does not necessarily rewrite the configuration that made normal UPDI unavailable.

It may temporarily override the configured pin behavior.

Depending on the device implementation, the original function can return after events such as:

power-on reset
programming exit
other reset/state transitions

Therefore HV activation may restore temporary access without permanently sacrificing the application’s configured pin function.

If permanent ordinary UPDI availability is desired afterward, the relevant configuration may need to be changed deliberately.


32. The Special Problem of a UPDI Pin Configured as an Output

Suppose a shared UPDI/GPIO pin is currently being driven by application firmware as:

GPIO output LOW

and an external programmer suddenly applies:

12 V

to that same node.

The MCU output transistor may be trying to pull the line toward ground while the programmer attempts to raise it toward 12 V.

Possible consequences include:

  • excessive current;
  • pad stress;
  • damaged external circuitry;
  • disturbed target power;
  • failed activation.

This is why applicable HV recovery procedures may involve RESET or target power sequencing.

The application should not be allowed to establish an opposing output state before the activation pulse is applied.


33. Safe Power-Toggle HV Entry

A safer shared-pin recovery strategy is conceptually:

1. Remove target power.

2. Ensure the programmer's target driver is released.

3. Restore target power.

4. Detect that VDD has risen.

5. Before application firmware actively drives the shared pin:
       apply the correct HV activation pulse.

6. Remove HV.

7. Establish ordinary UPDI communication.

8. Send the required key within the allowed interval.

Target power control is therefore useful for more than convenience.

It can become part of safe and repeatable HV recovery.

Our finalized hardware reserves:

Nano D8 = TARGET_POWER_ENABLE

and includes an optional relay-controlled target-power stage.

The first experiments do not require that section to be populated, but the hardware and firmware architecture already reserve the capability.

That means automatic power-cycle recovery can be added without changing the Nano pin assignments later.


34. Why We Use an External Bench Supply for HV

Generating 12 V onboard would be entirely practical.

Possible circuits include:

  • boost converter;
  • charge pump;
  • flyback converter;
  • dedicated programming-voltage generator.

But that would obscure the subject.

Our purpose is to understand UPDI.

Therefore our experimental programmer uses:

bench supply
      |
      v
HV switching circuit
      |
      v
target activation node

The Arduino controls only:

when

and:

where

the external voltage is applied.

It does not generate that voltage itself.

This provides several advantages.

First:

different target families can use different HV settings

Second:

voltage and current are directly observable

Third:

we avoid adding a switching-converter project

Fourth:

a current-limited bench supply adds another layer of experimental protection

The final hardware also measures the external HV rail using Nano A1.


35. The Arduino Must Never See the HV Rail Directly

A safe conceptual arrangement looks like this:

                   CURRENT-LIMITED BENCH SUPPLY
                              |
                           HV INPUT
                              |
                    +------------------+
                    | HIGH-SIDE SWITCH |
                    +------------------+
                              |
                       series resistor
                              |
                       HV ROUTE / ARM
                         /          \
                        /            \
                 RESET-HV          HV_OUT

The Nano controls that stage only through:

D7 = HV_ENABLE

A low-voltage NPN/PNP transistor arrangement isolates the Nano control signal from the high-voltage source.

The hardware defaults to HV OFF.

In addition, the normal UPDI data connection is also translated.

The Nano does not directly touch the target UPDI voltage:

                          TARGET DOMAIN

                            TARGET UPDI
                               |
               +---------------+---------------+
               |                               |
         open-collector TX                RX translator
               |                               |
               |                               |
Nano D6 -------+                               +------- Nano D5
 UPDI_TX                                               UPDI_RX


                           NANO DOMAIN

This means the same target conductor can operate at:

lower target logic voltages
normal 5 V logic

and, on applicable older devices, tolerate an intentional:

approximately 12 V UPDI activation pulse

without applying that voltage directly to the Nano GPIO pins.

The high-voltage output is also not permanently wired to RESET.

A physical route/arm selector allows the switched HV source to be directed appropriately for the target family or disconnected entirely.

That is deliberate.

Different UPDI generations use different activation destinations.


36. Why an Arduino Nano Is a Good Teaching Platform

The classic Nano gives us:

  • ATmega328P;
  • 16 MHz clock;
  • 5 V logic;
  • USB-to-serial interface;
  • Arduino IDE support;
  • hardware UART;
  • timers;
  • predictable GPIO;
  • enormous community familiarity.

Most importantly, it is fast enough to implement a useful UPDI bit engine in software.

The well-known jtag2updi project demonstrates that an ATmega328P-class Arduino can successfully implement UPDI timing and communication.

Its traditional implementation commonly uses:

Arduino D6 / PD6

as a single bidirectional UPDI GPIO.

Our final article hardware deliberately departs from that electrical arrangement.

We retain D6 as the transmit-control pin:

D6 = UPDI_TX

but add:

D5 = UPDI_RX

for a separately translated receive path.

Two small-signal NPN transistors combine those internal signals into the target’s single physical UPDI conductor.

This gives us:

  • voltage translation;
  • easier RX/TX handling;
  • better isolation;
  • and much better protection from an older 12 V-on-UPDI activation event.

The basic software timing ideas remain very similar.


37. Our Final Nano UPDI Interface

A minimal same-voltage experiment can indeed be built as:

Nano D6 ---- 4.7 kΩ ---- target UPDI

That remains a useful teaching example because it explains why extremely simple Arduino UPDI programmers can work.

Our final reference hardware is intentionally more capable.

Transmit path

The transmitter uses an NPN transistor as an open-collector pull-down.

Conceptually:

Nano D6 / UPDI_TX
        |
      47 kΩ
        |
      base
       QTX
    2N3904
       |
collector
       |
       +---------------- TARGET UPDI
       |
     emitter
       |
      GND

A base-emitter pull-down keeps QTX off while the Nano pin is floating during reset.

When D6 activates QTX:

TARGET UPDI → LOW

When D6 turns QTX off:

TARGET UPDI → released

The Nano never drives the target HIGH.

This is important.

The target’s own voltage domain determines the HIGH level.


Receive path

The receiver uses another NPN transistor.

Conceptually:

TARGET UPDI
     |
   47 kΩ
     |
    base
     QRX
   2N3904
     |
   emitter
     |
    GND

QRX collector
     |
     +---------------- Nano D5 / UPDI_RX
     |
   47 kΩ
     |
    +5 V

When target UPDI is HIGH:

QRX turns ON

and Nano D5 becomes:

LOW

When target UPDI is LOW:

QRX turns OFF

and D5 is pulled:

HIGH

The receiver is therefore electrically inverted.


Transmit is also logically inverted

For the TX transistor:

Nano D6 HIGH
     |
     v
QTX ON
     |
     v
target UPDI LOW

while:

Nano D6 LOW
     |
     v
QTX OFF
     |
     v
target UPDI released HIGH

Firmware therefore hides the transistor polarity behind logical physical-layer operations such as:

driveLow()
releaseLine()
readLine()

rather than allowing transistor polarity to leak into the rest of the protocol code.


Optional UPDI pull-up assistance

The target normally supplies the UPDI idle-HIGH behavior.

Our schematic nevertheless includes an optional external pull-up branch:

VTARGET
   |
Schottky diode
   |
33 kΩ
DNP
   |
TARGET UPDI

The resistor is:

DNP — Do Not Populate by default.

It exists only as a tuning option.

If oscilloscope testing shows that a particular target/cable/baud combination benefits from stronger pull-up assistance, the resistor can be fitted.

The series diode allows the branch to source current from VTARGET during normal operation while greatly reducing reverse current from an intentional 12 V UPDI activation pulse back into VTARGET.

The final schematic therefore does not assume that the auxiliary pull-up is required.

Testing will decide that.


Voltage range

The transistor interface is intended to make the programmer usable over a much wider target-voltage range than a bare 5 V Nano GPIO.

We will specifically test it at representative target supplies including:

1.8 V
3.3 V
5.0 V

and at several UPDI communication speeds.

Until those tests are complete, we should describe this as:

designed for low-voltage target support

rather than claiming guaranteed operation at every voltage and baud-rate combination.

That is the difference between design intent and qualification.


38. Final Nano Pin Assignment

The finalized programmer assigns:

Nano pinFunction
D2Activity indication
D3HV/status indication
D4TARGET_RESET_CTRL
D5UPDI_RX
D6UPDI_TX
D7HV_ENABLE
D8TARGET_POWER_ENABLE
A0VTARGET_SENSE
A1HV_SENSE

Additional pins are available for optional:

SPI expansion
I²C expansion

The important UPDI point is:

D6 = transmit
D5 = receive

inside the programmer.

At the target connector those two signals become:

one UPDI conductor.

39. The Programmer Has Two Serial Links

Our Nano programmer participates in two completely different serial conversations.

The first is:

PC <---- USB serial ----> Arduino Nano

The second is:

Arduino Nano
      |
D6 TX / D5 RX
      |
UPDI translator
      |
single-wire UPDI
      |
target AVR

They are not the same protocol.

The PC-to-Nano link might use:

115200 baud
8N1

or another convenient host rate.

The target link might use:

UPDI bit timing
8E2
SYNCH
BREAK
ACK
half-duplex transaction rules

Graphically:

+------------+
| PC         |
|            |
| host tool  |
+-----+------+
      |
      | USB serial
      | HOST PROTOCOL
      |
+-----v------+
| Arduino    |
| Nano       |
|            |
| D6 TX      |
| D5 RX      |
+-----+------+
      |
      | transistor translation
      |
      | one-wire UPDI
      |
+-----v------+
| Target AVR |
+------------+

This distinction is essential.


40. Our Programmer Firmware Should Be Layered the Same Way

Rather than writing one enormous Arduino sketch, we divide responsibilities.

A sensible architecture is:

NanoUPDI/
|
+-- NanoUPDI.ino
|
+-- updi_phy.h
+-- updi_phy.cpp
|
+-- updi_link.h
+-- updi_link.cpp
|
+-- updi_commands.h
+-- updi_commands.cpp
|
+-- updi_nvm.h
+-- updi_nvm.cpp
|
+-- updi_device.h
+-- updi_device.cpp
|
+-- voltage_sense.h
+-- voltage_sense.cpp
|
+-- hv_control.h
+-- hv_control.cpp
|
+-- host_protocol.h
+-- host_protocol.cpp
|
+-- tests/

Conceptually:

updi_phy
    |
    +-- drive target UPDI LOW through TX transistor
    +-- release target UPDI
    +-- read inverted RX state
    +-- send bit
    +-- receive bit
    +-- send byte 8E2
    +-- receive byte 8E2
    +-- BREAK


updi_link
    |
    +-- SYNCH
    +-- ACK
    +-- recovery
    +-- transaction timing
    +-- turnaround


updi_commands
    |
    +-- LDS
    +-- STS
    +-- LD
    +-- ST
    +-- LDCS
    +-- STCS
    +-- REPEAT
    +-- KEY


updi_nvm
    |
    +-- enter programming mode
    +-- chip erase
    +-- Flash erase
    +-- Flash write
    +-- EEPROM
    +-- fuses


voltage_sense
    |
    +-- VTARGET
    +-- HV input/output validation


hv_control
    |
    +-- HV switching
    +-- routing
    +-- timing
    +-- safety interlocks


host_protocol
    |
    +-- PC/Nano communication

The new two-pin translator means the physical layer no longer has to repeatedly change one GPIO between:

INPUT

and:

OUTPUT

states.

Instead, transmit and receive hardware remain available independently.

The target line itself is still half-duplex.

That simplifies implementation without changing UPDI semantics.


41. Our First Development Milestones

We will not begin by attempting to upload a Blink sketch.

The project will progress in controlled stages.

Milestone 1

Nano generates accurate UPDI 8E2 timing.

Milestone 2

TX transistor produces the expected target-side waveform.

Milestone 3

RX transistor reliably returns the target line state.

Milestone 4

Nano generates robust BREAK.

Milestone 5

Nano sends SYNCH successfully.

Milestone 6

Nano reads a UPDI control/status register.

Milestone 7

Nano reads target identification/signature.

Milestone 8

Nano enters NVM programming mode.

Milestone 9

Nano reads Flash.

Milestone 10

Nano performs chip erase.

Milestone 11

Nano writes and verifies Flash.

Milestone 12

Nano reads/writes EEPROM.

Milestone 13

Fuse support with safeguards.

Milestone 14

VTARGET and HV measurement qualification.

Milestone 15

External-HV recovery.

Milestone 16

Host-side programming utility integration.

Milestone 17

Explore OCD/debug support.

Every destructive feature comes after read-only communications have been demonstrated.

That is safer and substantially easier to debug.


42. A Note About Debugging

UPDI is not merely capable of programming.

The interface connects to the AVR’s:

On-Chip Debug system — OCD

Applicable devices provide capabilities including:

  • memory-mapped access to NVM, RAM, and I/O;
  • program run/stop/reset control;
  • hardware breakpoints;
  • software/user-program breakpoints;
  • PC observation;
  • stack-pointer observation;
  • status-register observation;
  • register access;
  • nonintrusive runtime monitoring features.

So conceptually:

single target UPDI wire
        |
        v
      UPDI
        |
        +-------- NVM programming
        |
        +-------- memory access
        |
        +-------- OCD
                    |
                    +-- halt
                    +-- run
                    +-- reset
                    +-- breakpoint
                    +-- inspect CPU state

But implementing a useful debugger is substantially more difficult than implementing a programmer.

Why?

Because a debugger involves at least two major tasks:

communicate with the target's OCD machinery

and

present that functionality to a host debugger/IDE

We will therefore build programming first.

Only after the electrical layer and memory operations are proven will we add the debugging architecture.


43. What We Now Know

At this point UPDI should no longer seem like mysterious Microchip magic.

At its heart it is surprisingly understandable.

Electrically

At the target:

one bidirectional UPDI signal
common ground
optional VTARGET reference/power
optional RESET

Our programmer internally implements that one bidirectional signal using:

separate TX and RX transistor paths

for level translation and protection.

That is an implementation detail of the programmer.

It does not change UPDI itself.

At the serial/data-link level

UART-like
half duplex
8E2
BREAK
SYNCH 0x55
ACK

At the instruction level

LDS
STS
LD
ST
LDCS
STCS
REPEAT
KEY

At the programming level

UPDI memory access
        +
target-specific NVMCTRL procedure
        =
Flash / EEPROM / fuse programming

At the debugging level

UPDI
  +
OCD
  =
single-wire on-chip debugging

And high voltage is not the voltage used to burn Flash.

It is a temporary interface-activation mechanism required by certain target pin arrangements.

Most importantly:

12 V is not universal.

Older shared-pin arrangements may use the 12 V class.

Dedicated-UPDI devices ordinarily do not require HV simply to make UPDI physically available.

Some newer devices use a lower target-specific activation voltage, frequently around:

VDD + 2 V

on a separate RESET pin.

Always consult the exact target documentation before applying high voltage.


44. Where We Go Next

In Part II we move from theory to actual hardware and firmware.

We will build the Arduino Nano UPDI interface from the ground up and examine:

  • the complete Nano reference schematic;
  • the four-pin target connector;
  • why UPDI remains one external wire even though our programmer internally uses two GPIOs;
  • D6 = UPDI_TX;
  • D5 = UPDI_RX;
  • the two-transistor level translator;
  • open-collector target transmission;
  • inverted receive logic;
  • target-voltage translation;
  • the optional DNP target-side pull-up;
  • the Schottky isolation used with that optional pull-up;
  • tolerance of the older 12 V-on-UPDI activation case;
  • A0 = VTARGET_SENSE;
  • A1 = HV_SENSE;
  • the target-voltage ADC divider and input protection;
  • the HV divider and its approximately 18 V comfortable measurement range;
  • D4 = TARGET_RESET_CTRL;
  • D7 = HV_ENABLE;
  • D8 = TARGET_POWER_ENABLE;
  • physical HV route/arm selection;
  • why naïve level shifting can interfere with UPDI;
  • waveform and rise-time testing;
  • target operation at representative 1.8 V, 3.3 V, and 5 V supplies;
  • UPDI timing;
  • implementing 8E2 in software;
  • generating even parity;
  • generating BREAK correctly;
  • sending 0x55 SYNCH;
  • receiving target responses;
  • turnaround timing;
  • detecting parity and framing errors;
  • implementing LDCS;
  • implementing STCS;
  • implementing LDS;
  • implementing STS;
  • implementing LD and ST;
  • implementing REPEAT;
  • implementing KEY;
  • reading the System Information Block;
  • obtaining target identification;
  • building a simple host command console;
  • and validating each layer before destructive programming is allowed.

Part III then builds the actual programmer:

  • programming-mode entry;
  • NVM keys;
  • NVM-controller generations;
  • Flash reads;
  • chip erase;
  • page erase/write;
  • verification;
  • EEPROM;
  • fuses;
  • USERROW;
  • lock handling;
  • recovery;
  • Intel HEX;
  • and the Python host utility.

Part IV covers high-voltage recovery in detail:

  • old 12 V-class activation;
  • newer RESET-HV activation;
  • externally supplied bench HV;
  • transistor switching;
  • HV measurement;
  • physical route/arm control;
  • target power sequencing;
  • pulse timing;
  • the key-acceptance window;
  • output-pin contention;
  • device-family safety rules;
  • and actual recovery procedures.

Part V examines UPDI debugging:

  • OCD architecture;
  • entering debug mode;
  • halt and run control;
  • reset;
  • single stepping;
  • PC/SP/SREG access;
  • CPU register inspection;
  • SRAM and peripheral inspection;
  • hardware breakpoints;
  • software breakpoints;
  • GDB Remote Serial Protocol;
  • the division of responsibility between Nano and PC;
  • and the parts of the low-level OCD interface that require experimental or community-derived knowledge.

Finally, Part VI integrates the whole project into a practical reference:

  • final system architecture;
  • reference wiring;
  • programmer operation;
  • high-voltage operation;
  • debugging workflow;
  • automated testing;
  • failure diagnosis;
  • oscilloscope and analyzer procedures;
  • host-software architecture;
  • Git/test strategy;
  • engineering notes;
  • and a curated resource directory.

By that point we will not merely know how to use UPDI.

We will understand enough of it to build, test, program, recover, analyze, and debug through the machinery that uses it.

Leave a Reply

Your email address will not be published. Required fields are marked *