Skip to content

UPDI Serial Programming

Profile Picture Teddy Warner| Summer & Winter, 2021 | 24-31 minutes

Many modern small chipsets rely on the Unified Program and Debug Interface (UPDI), a one-wire interface allowing for the changing of fuzes, burning of bootloaders, or uploading of sketches to any AVR Dx-series parts or any modern AVR Microcontrollers. Due to their reliance on the Unified Program and Debug Interface, these parts cannot be programmed with classic ISP style programmers, and thus a UPDI enabled programmer is required. Although UPDI is the only programming option in the case of these parts, the one-wire interface is superior to the four-wire of a classic ISP programmer and allows for quicker programming setup and less cluttered boards due to fewer programming pins. This USB-C UPDI programmer is built with a Ft232rl chip allowing for serial interfacing, and runs alongside the megaTinyCore library witch equips your IDE for serial UPDI programming via a portable python implementation.

megaTinyCore Documentation

In short, the megaTinyCore library is “An Arduino core for the tinyAVR 0-series, 1-series, and now the 2-series”1. The megaTinyCore project was created and maintained by SpenceKonde. As mentioned above, the library equips your IDE for UPDI programming via a portable python installation and can be used alongside a handful of different programmer types. The USB-C UPDI Serial programmer documented alter on this page is currently the optimal choice out of these options due to its low component requirement and faster speeds than other programmers. In addition to serial programmers, One can use a 328p based board as a programmer (i.e. an Arduino or any of its clones) via megaTinyCore’s jtag2updi sketch, or a designated microchip programming board or and UPDI programming tool that mimicks any listed above. Dr. Adam Harris, a mentor of mine during my cycle of Fab Academy has a Simple Fab-jtag2UPDI Board project where a 328p based board is used alongside the jtag2UPDI sketch and is a great option when creating an In-Circuit programmer though the library. I manufactured this board during my Electronics Production and continued to use it for the next 16 weeks of the course.

Package Installation

Software Requirement

Arduino 1.8.13 is recommended for use with the megaTinyCore library

Recent updates to the megaTinyCore library have simplified the installation process significantly. The library relies upon a board package that can be installed via the board manager witch can be installed with 3 simple steps included below2.
  1. File -> Preferences, enter the above URL in Additional Boards Manager URLs
  2. Tools -> Boards -> Boards Manager…
  3. Select megaTinyCore by Spence Konde and click “Install”. For best results, choose the most recent version.

jtag2UPDI Programming


As mentioned prior, jtag2updi is a sketch from the megaTinyCore library, allowing for the use of a 328p-based board (i.e. Arduino or a clone) as an In-Circuit programmer. To begin with, this programming approach, download the latest version of the jtag2udpi sketch via the button below (Code -> Download Zip).

Download the Latest jtag2udpi Sketch

Extract the contents of this downloaded sketch folder by first unzipping the downloaded folder and next moving the contained sketch folder in the unzipped folder to a separate location. Finally, Rename this sketch folder to jtag2updi, leaving you with a folder similar to the one circled in red in the image below.

Inside of this jtag2updi folder, navigate to the jtag2UPDI.ino project - circled and highlighted below - and open it in your IDE.

This will open the jtag2updi project file system, leaving you with a blank jtag2updi sketch followed by multiple file tabs in your IDE (like shown in the picture below).

You can next upload this sketch to your 328p-based board of choice as you would any other sketch.


As a first test to confirm the successful upload of this sketch to your board, hook up an LED to pin 6 of the board. If the board is successfully programmed, the LED will be dimly lit as shown below. This simple test eliminates a potential error while troubleshooting a project, and confirms the programmer’s working condition.

Once a board is programmed with the jtag2updi project, it will act as a programmer until the next sketch is uploaded, unless the board’s reset line is cut.

jtag2UPDI Usage

To make use of a jtag2updi enabled In-Circuit programmer board, prepare a sketch in your IDE to upload to your desired board. For documentation purposes, I’ll be uploading the simple blink sketch included below to a super simple ATtiny 412 based LED board I made in week 4 of my Fab Academy cycle and documenting it for use with the Arduino IDE.

void setup() {
  pinMode(0, OUTPUT);

void loop() {
  digitalWrite(0, HIGH); 
  digitalWrite(0, LOW); 

To upload code to your board via your jtag2updi enabled In-Circuit programmer board …

  1. Wire your board to your jtag2updi In-Circuit Programmer board - UPDI pin of the board to pin 6 of jtag2updi In-Circuit Programmer board with an inline 100-470 ohm resistor running between the UPDI pin and the In-Circuit Programmer, VCC to VCC, and GND to GND
  2. Under the Tools menu in the Arduino IDE, change your board to your board’s chipset by navigating to the megaTinyCore board menu via Tools -> Board -> megaTinyCore and then selecting your chip group from the list.
  3. Next, specify your chip type under the Chip menu via Tools -> Chip.
  4. For use with you jtag2updi In-Circuit Programmer board, change the programmer option to Tools–>Programmer –> jtag2updi
  5. Change your COM port to connect via serial to your In-Circuit Programmer board if not already connected
  6. Finally, upload your sketch via the Upload Using Programmer button found under the IDE’s Sketch menu - Not with the normal upload button (this will override your programmers jtag2updi sketch if done).


Following these steps on my simple ATtiny 412 board yielded the 1/2 second blink example below.


You can now program any modern AVR Microcontrollers via UPDI and a jtag2updi enabled 328p-based board.

Serial Programming


Serial UPDI Programming with megaTinyCore

Version 2.2.0 of the megaTinyCore library brings the implementation of a portable python implementation. This installation, based on pymcuprog, allows for a programming speed increase by a factor of 20 when compared to the prior jtag2udpi programming style. With this performance increase in addition to a smaller & cheaper hardware list, Serial UDPI programming with the megaTinyCore library is the most optimal form of programming I’ve used on my boards to date.

The serial programming style relies on this prior mentioned portable python installation alongside a USB-Serial adapter acting as the programmer in this case. Though this section of the page will document this programming style via a pre-made USB-Serial adapter (in this case an FTDI chip) and some other hardware bits, please note the USB-C UPDI Serial Programmer board documented later on this page - this board is a set hardware piece for this Serial UPDI programming style, and provides a permanent hardware programming board. To engage the Serial UPDI programming method without a board like this you’ll need the required hardware…

  1. A USB-Serial Adapter - I’ll be using an FTDI FT232 for this documentation, but boards based on the CH340G or the CP210 chips work great as well
  2. Some Jumper Wires
  3. A Schottky Diode - I tacked some leads to an SMD package (as shown below), but if you can get your hands on a through-hole package, that works great as well.
  4. A 470-ohm Resistor - If creating a UPDI programmable board, incorporate this resistor into your schematic using the pinout below, running the 470-ohm resistor inline to the UPDI pin. Any value between 100 and 1k ohms will do here, but 470 is the optimal value.
Target Board Programming Headers
-----| UPDI---\/\/------>
-----| Gnd    470 ohms (100 ~ 1k)
-----| Vcc

If not creating your own board, and there’s no inline UPDI resistor, you’ll need to include this resistor externally. With that said, wiring between your serial adapter and the target device is diagrammed in the schematics below.

  • VCC of Adapter to VCC of Target
  • GND of Adapter to GND of Target
  • Schottky Diode between the Rx & Tx of Serial Adapter (Cathode to Tx)
  • Rx of Adapter to UPDI of Target - Here include the 470 ohms resistor as needed
Ideal - internal resistor in the adapter - not more than 1k
--------------------                                 To Target device
                DTR|                                  __________________
    internal    Rx |--------------,------------------| UPDI---\/\/------>
  Tx---/\/\/\---Tx |-------|<|---'          .--------| Gnd    470 ohms (100 ~ 1k)
    resistor    Vcc|---------------------------------| Vcc
  typ. 1k       CTS|                     .`          |__________________
                Gnd|--------------------'             If you make a 3-pin connector, use this pinout


--------------------                                 To Target device
                DTR|     External 470 ohms (100 ~ 1k) __________________
    internal    Rx |--------------,--\/\/------------| UPDI------------->
  Tx---/\/\/\---Tx |-------|<|---'          .--------| Gnd
    resistor    Vcc|---------------------------------| Vcc
  typ 1k        CTS|                     .`          |__________________
Or with no internal resistor on the adapter - as long as the target has one
--------------------                                 To Target device
                DTR|                                  __________________
       no       Rx |--------------,------------------| UPDI---\/\/------>
    internal    Tx |-------|<|---'          .--------| Gnd    470 ohms (100 ~ 1k)
    resistor    Vcc|---------------------------------| Vcc
                CTS|                     .`          |__________________

I rigged up the second included schematic on a breadboard as unfortunately the blinky board I’m programming doesn’t have a valid inline resistor I can use.

Serial Programmer Setup on a Breadboard

Serial Programmer Usage

To program via your USB-Serial setup …

  1. Navigate to the Tools -> Programmer menu and select an iteration of the Serial-UPDI options (Based on upload speeds, the tinyAVR core offers 57600 baud, 230400 baud, and 460800 baud options - thus the different speed settings)
  2. Then, under Tools -> Port select the port connected to your USB-Serial adapter, if not already selected
  3. Finally, upload your sketch via the Upload button and watch as your board is programmed at lightning speeds!

Note - this serial programmer setup does not give you a serial monitor

You’ll need to connect a serial adapter the normal way for that. The later documented USB-C UPDI Serial Programmer & ftdi2updi boards provide a switching feature between a serial programming and serial monitoring mode, allowing for all programming and monitoring work to be done without rework of connections. Be sure to check out the specific USB-C UPDI Serial Programmer usage section for use of this feature.


For this example, I modified my prior used blink sketch to run a 5-second delay as opposed to the prior 0.5 seconds…

void setup() {
  pinMode(0, OUTPUT);

void loop() {
  digitalWrite(0, HIGH); 
  digitalWrite(0, LOW); 

I uploaded this via the three-step process listed above, yielding the successful results below.


You can now program any modern AVR Microcontrollers via UPDI with a simple USB-Serial adapter with a speed increase by a factor of twenty when compared with the prior jtag2updi method.

UPDI Serial Programmer Manufacturing

I made countless PCBs during my cycle of the Fab Academy, one of the first being a tool to program the rest, an In-Circuit Programmer. Being one of the first boards I fabricated myself, from the PCB milling to soldering & stuffing, I hadn’t yet taken up the practice of designing my boards, and for this assignment, fabricated the In-Circuit Programmer design of one of my mentors, Dr. Adam Harris. This board is a specialized Arduino-like board, running on an ATMega 328p with a programmer sketch provided by the megaTinyCore library.

Project Origins

The In-Circuit Programmer I fabricated in Fab Academy’s operation is great, but due to new updates in the megaTinyCore library, the process can be optimized for faster speeds, and the board size and component requirements can be reduced. This board marks my first steps into the world of multi-layered PCB design and fabrication, a process I’m super pumped to pick up and apply to future projects.

The USB-C UPDI Programmer is a specialized piece of hardware for use with the prior discussed serial programming method and has a couple of advantages over rigging a programmer up on a breadboard. A permanent piece of the hardware enables the serial programming method to require a bit less setup, once the board has been made. Following that, this board includes “modes”, allowing switching between serial programming and monitoring functions. When rigging a serial programmer up via a USB-serial adapter as documented prior, you cannot monitor serial from the board at the same time, but instead are required to require the board to the USB-serial adapter. The switching of “modes” on this programmer eliminates this extra hassle, handling all the required connections at the flip of a switch located on the board’s underside.


It was this elimination of hassle that pushed me to create this piece of hardware, yielding a simple workflow when serial programming. The USB-C UPDI Serial Programmer is based on the FT232RL3 IC, handling the USB protocol and USB to serial data transfer on the programmer.

The FT232RL is broken out following the same wiring principals diagrammed in the prior serial programming documentation, converting the IC’s Rx and Tx lines to a UPDI line, routed to a programming pin. Just before this Rx and Tx junction, a Double-Pole Double-Through switch allows for the switching of this conversion to UPDI to straightforward Rx and Tx lines, routed each to their corresponding pin. Thus, the programmer board includes a UPDI, Rx, and Tx output pin, in addition to a VCC and GND line. This 5 pin programming pinout can be mimicked on any board containing a AVR Microcontroller, allowing for programming and monitoring functions to be switched without reworking connections between the programmer and board.

USB-C UPDI Programmer Eagle Schematic

Then came the nesting process. Being my first double-sided board in Eagle, it took some work to get used to the use of vias between sides, but eventually, I worked out the process of changing Via’s drill class through Eagle’s Change -> Drill tool. I ended up using 0.6mm rivets for this board’s vias, using 8 on the board in total. I nested bards on the board, including both the FT232RL and the USB-C female adapter on the top side, along with some smoothing capacitors, and on the bottom, the UPDI programming component array, as well as the DPDT switch.

USB-C UPDI Programmer Eagle Board

The nesting of the two highest pinout parts on the board’s topside inspired my next experiment with this board, Solder Paste Stencil making. Although I feel pretty confident in my SMD soldering skills, soldering pads this small wouldn’t only be a hassle, it would also be tedious time waste, and thus I settled on a solder paste stencil approach for the boards topside, while hand soldering the bottom half. I exported the Tcream layer of my programmer board from Eagle as a .pdf for cutting of the stencil from cardstock on a Epliog Fusion Pro 48 laser.

Tcream board layer in Eagle

Bill of Matierals - USB-C UPDI

Qty. Part Cost URL
x1 SMD DPDT Switch $1.50 link
x1 CDBM1100-G $0.39 link
x1 470 ohm SMD Resistor $0.10 link
x1 1.5k ohm SMD Resistor $0.10 link
x1 100nf SMD Cap $0.18 link
x1 1uf SMD Cap $0.10 link
x1 DX07S016JA1R1500 $1.59 link
x1 FT232RL $4.19 link
x11 Header Pins $0.14 link
x1 Copper PCB Blank $0.70 link

Total Cost- $8.99

ftdi2updi Design

In addition to the prior USB-C UPDI Serial Programmer board, I created an alternative hardware programmer that makes use of a pre-existing FTDI chip, enabling it with the same switching functions feature as the prior board. This provided a workaround to 2021’s silicone shortage, as due to backed-up supply chains, I wasn’t able to get my hands on the FT232RL right away.

The board’s schematic is a cloned iteration of the prior programmer, but with the USB-C & FT232RL components removed, and replaced with headers for connection to an FTDI adapter, yielding the schematic below.

First Iteration ftdi2updi Programmer Eagle Schematic

I was compelled to expand on the original shape of an FTDI serial adapter for this board, as it expands on the functionality of the adapter itself. I used Inkscape to create the board shape, allowing for meshing with an FTDI serial adapter, with the board aligning two of the sides of the adapter and then imported this board shape into Eagle via an ulp as documented on my Fab Academy Final Project page. I then nested the components on both sides of the board, aligning the FTDI connection pins allowing for proper seating of the FTDI serial adapter with the board.

First Iteration ftdi2updi Programmer Eagle Board

Bill of Matierals - ftdi2updi

Qty. Part Cost URL
x1 SMD DPDT Switch $1.50 link
x1 CDBM1100-G $0.39 link
x1 470 ohm SMD Resistor $0.10 link
x11 Header Pins $0.14 link
x1 Copper PCB Blank $0.70 link
x1 FTDI Serial Adapter $14.95 link

Total Cost (W/out FTDI)- $2.83

Final Cost- $17.78

Fabrication & Testing


I milled my boards with a Bantam PCB mill and its Bantam Tools Desktop Milling Machine Software. The software handles all toolpath generation from my Eagle board file, and conveniently, when paired with Bantam’s PCB placement bracket, also handles the double-sided board milling process via a toggle switch in the interface. I followed the same milling process I have documented on my week 4 Fab Academy page, however after the top-side traces and holes were milled, I flipped the copper stock, aligning to the right-hand corner of the PCB alignment bracket as opposed to the left, and toggled the board to its bottom side in the Bantam Tools Desktop Milling Machine Software. With the stock realigned, I repeated the same milling process for the bottom side of the board. This whole process is showcased in this view from Bantam.

I used a 0.005” PCB engraving bit for the ftdi2updi’s traces, and a 1/32” for its holes and outlines, yielding the milled results below.

After the milling, I washed off my board with some soap and water. The Bantam Tools Desktop Milling Machine Software makes the milling of double-sided boards super straightforward, not much harder than a single-sided PCB, however, the boards require the extra step of riveting vias between both sides of the board before soldering. This article on PCB Rivets from the Fab Docs walks through the process down into a couple of steps.

First the via has to be inserted into its corresponding hole, I used 0.6mm vias here. Then I used a V-Shaped nail to chamfer the top of the via and finally pressed it flush with a flat press, each step shown in the three images below.

Finally, to ensure a proper connection, I soldered over each side of the via and repeated this process for all four of the board’s vias.

Boards with Vias

I finished the stuffing and soldering of this board, a simple enough process due to the small component size.


The board that is being documented here is an early iteration of the ftdi2updi and contains an extra resistor, and thus your final board may not look exactly like the ones on this page until the Programmer Usage section.

I ran two tests on the ftdi2updi, one proving each of the board’s functions.

Programming Test

Beginning with its programming function, I uploaded a modified version of the same blink test sketch used above to my simple LED board …

void setup() {
  pinMode(0, OUTPUT);

void loop() {
  digitalWrite(0, HIGH); 
  digitalWrite(0, LOW); 

I uploaded this via the Programmer Usage process documented in the corresponding section below. The first upload was successful at a medium (230400) baudrate. Then I uploaded the test, and repeated it at the highest (TURBO 4.5v + 460800) baudrate, yielding the successful results below.


The ftdi2updi serial adapter meshing headers were reversed in this iteration, and thus I attached the serial adapter upsidedown for this test, the proper orientation as outlined in the following Programmer Usage section.

Serial Monitoring Test

Next, I switched the programmer to its monitoring mode and hooked it up to Arduino RX & TX pins, shown below. Unfortunately, my simple LED board doesn’t have serial communication pins, and thus this Arduino was my next best testing option.

I uploaded this super simple serial print sketch to the Arduino …

void setup(){

void loop(){
  Serial.println("Hello World");

and then opened the Arduino IDE’s serial monitor on my ftdi2updi port, which successfully read the serial output printed, shown below - and also was able to transmit via serial, shown by the Arduinos receiving LED.

Although this first iteration of the ftdi2updi worked, there were a couple of design flaws (Noted above) I’ve flatted out in later versions including - a reversed FTDI header, oversized vias, an unnecessary 1k resistor, and improper meshing with an existing FTDI serial adapter. The final version of this programmer (and its CAM files) can be accessed in the repo linked by the download button at the bottom of the Fabrication & Testing section. Use this version as refrence whilst fabricating your own board.

I ordered a couple of these final iteration boards from a PCB fab …

Which turned out incredible. The Gerber files for these boards are included in the Repo linked via the download button at the bottom of the Fabrication & Testing section, along with an Eagle board file with silkscreen decals instead of milled ones. I soldered the components to this board, a process made even easier by the already plated vias, and lack of need to insert my own.

ftdi2updi Front and Back

Download the FTDI2UPDI Files


Pending Compleation

As mentioned prior, due to 2021’s supply chain limitations, I cannot currently get my hands on an FT232RL, and thus, for now, the fabrication & testing sections will only include my ftdi2upid board. This section will be updated by future me once I can get an FT232RL.

This USB-C UPDI Programmer Board is not yet complete

Although you can download its files, the board is still in development and may not function properly. Again, this section will be updated upon its completion.

  • Process Type - Vector
  • Speed - 100.0%
  • Power - 19.0%
  • Frequency - 6.0%

Download the USB-C UPDI Files

Programmer Usage

Serial programming with the megaTinyCore library is incredibly straightforward, and when pair with the switching functionality of both of my hardware programmers, the process is streamlined. I’ll be using a final iteration ftdi2updi board for this Programmer Usage documentation, however, these steps will work for either programmer style included on this page, regardless of fabrication technique.

Both Serial UPDI programmers rely on the prior documented megaTinyCore library, which must be installed for programmer usage. This process is outlined in the Package Installation section of this page.


To use the UPDI programming function, toggle the programmers switch to UPDI as shown below, and then connect UPDI and GND lines to their corresponding pins. Here you can also run a VCC line to your target board, which provides 5v, shown in the wiring below.


Connecting serial data lines here is totally ok, as the switch disconnects them from communication when in programming mode. The wiring shown here is just the required connections for UPDI programming.

Switched to Progamming Mode

Minimum Wiring for UPDI Programming

Once connections are made between the programmer and the target board, you must configure your target board in your IDE. For this documentation, I’ll continue using the Arduino IDE, however other IDEs with the megaTinyCore installed can be used for this (I may do some tests with PlatformIO in the future, and will update this page accordingly).

First, you must select your target board’s microcontroller by navigating to …

Tools > Board > megaTinyCore

and then selecting your microcontroller from the list, shown in the image below.

Next, connect your programmer to your computer via a serial cable and, select your serial port by navigating to …

Tools > Port

and then select the serial port your programmer board is connected to (In my case this port was COM11 - shown below). If you’re on windows, you can find this connection on Device Manager before your selection in the IDE.

Finally, select your programming style. For all programmers documented on this page, the Serial UPDI w/ 4.7k resistor or diode series of styles are used, and you can select between three baudrate/speed options (highlighted in the image below) …

  • SLOW (57600 baud)
  • (230400 baud)
  • (TURBO 4.5v + 460800 baud)


To use the serial monitoring function, toggle the programmers switch to Serial as shown below, and then connect Transmitting and Receiving Data lines as well as GND to their corresponding pins. Keep in Mind RX and TX lines must be switched between the programmer board and the target, with Transmitting of one going to Receiving of the other and vise versa. Here, as prior, you can also run a VCC line to your target board, which provides 5v.


Connecting the UPDI line here is totally ok, as the switch disconnects it from communication when in monitoring mode. The wiring shown here is just the required connections for Serial monitoring.

Switched to Monitoring Mode

Minimum Wiring for Serial Monitoring

To begin serial monitoring through the programmer in the Arduino IDE, first, ensure your programmer is connected to your computer via a serial cable, and the proper boart is selected in the IDE (as done in the prior programming section - and highlighted below). Then navigate to …

Tools > Serial Monitor 

as selected in the picture below

This will open the IDE’s serial terminal, where incoming serial data is printed, and outgoing data can be transmitted via the input at the top of the window. I wired a programmer to a simple “Hello World” printing Arduino, yielding the received results below.


You now know the methods to UPDI programming with the megaTinyCore library, and may have a cool hardware programmer to show for it 😁.