Background
In 2019, Microchip acquired Atmel and released several new AVR microcontrollers, including the Tiny-0 and Tiny-1 Series. On these mircocontrollers, traditional Atmel ICSP programming was not supported. Instead, they feature a new one-wire programming interface called Unified Programming and Debug Interface (UPDI). The new hardware also made existing TTL-serial bootloader programming obsolete. Thus, one must use a native UPDI programmer to work with these microcontrollers, such as pyupdi.
However, Optiboot's developers have subsquently developed a new version of the bootloader called Optiboot_X and implemented the STK500 programming protocol on these new microcontrollers, allowing one to program these microcontrollers using the traditional TTL-serial bootloader approach, and it appears that the Arduino community has already supported them for a while, with MegaCoreX and megaTinyCore, which was good news to me. Nevertheless, it seems that there's little resource beyond these prepackaged Arduino cores, in particular, there's almost no documentation on how to program them manually from the commandline.
What I've already done
I designed a custom AVR development board based on the Atmel ATTiny1604 microcontroller, which is a member of the new Tiny-0 family. Due to technical considerations, it must be programmed via the serial port using the bootloader similar to a traditional Arduino, not UPDI (UPDI is only used to burn the bootloader).
To achieve this goal, I installed the latest version of binutils, GCC and an experimental patch to avr-libc, so the compiler is able to generate code targeting my microcontroller. Then, I compiled my personal Optiboot_X bootloader.
$ git clone https://github.com/Optiboot/optiboot.git
$ cd optiboot/optiboot/bootloaders/optiboot
$ make -f Makefile.mega0 optiboot_attiny1604.hex UARTTX=A1 TIMEOUT=8 LED=A7 BAUD_RATE=57600 LED_START_FLASHES=10
Using Compiler at: /home/user/code/optiboot/optiboot/bootloaders/optiboot/avr-gcc
avr-gcc -g -Wall -Os -fno-split-wide-types -mrelax -DWDTTIME=8 -DLED_START_FLASHES=10 -DLED=A7 -DUARTTX=A1 -DBAUD_RATE=57600 -Wl,-section-start=.text=0 -Wl,--section-start=.application=0x200 -Wl,--section-start=.version=0x1fe -Wl,--relax -nostartfiles -nostdlib -mmcu=attiny1604 -o optiboot_attiny1604.elf optiboot_x.c
avr-size optiboot_attiny1604.elf
text data bss dec hex filename
494 9 0 503 1f7 optiboot_attiny1604.elf
avr-objdump -S optiboot_attiny1604.elf > optiboot_attiny1604.lst
avr-objcopy -j .text -j .data -j .version --set-section-flags .version=alloc,load -O ihex optiboot_attiny1604.elf optiboot_attiny1604.hex
Then I uploaded the Optiboot_X bootloader to the ATTiny1604 microcontroller via UPDI, using pyupdi
.
# set fuse BOOTEND
$ pyupdi -d tiny1604 -c /dev/ttyUSB0 -fs 8:0x02
# burn Optiboot_X
$ pyupdi -d tiny1604 -c /dev/ttyUSB0 -f optiboot_attiny1604.hex
# reset
$ pyupdi -d tiny1604 -c /dev/ttyUSB0 -r
After burning the Optiboot_X via UPDI, I was able to see 10 pulses during power-on at A7 on my oscilloscope, indicating that Optiboot_X was alive.
Note: Technically the installation is not complete yet. Since UPDI and /RESET
share the same pin, UPDI must be permanently disabled via fuse to allow programming via bootloader, but it means a nonfunctional bootloader can brick the chip. I decided to manually reset the chip by power cycling the board for now.
Next, I wrote a test program.
$ cat blink.c
#define F_CPU 20000000UL
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
PORTB.DIRSET = 0b00000001;
while(1) {
PORTB.OUTSET = 0b00000001;
_delay_ms(500);
PORTB.OUTCLR = 0b00000001;
_delay_ms(500);
}
}
And I compiled it.
$ make
avr-gcc -mmcu=attiny1604 -Wall -Os -o blink.elf blink.c
avr-objcopy -j .text -j .data -j .rodata -O ihex blink.elf blink.hex
Question
Now what? How do I upload blink.hex
to the Optiboot_X on the microcontroller?
On a traditional Arduino, the command is something like...
$ avrdude -C/etc/avrdude/avrdude.conf -v -patmega328p \
-carduino -P/dev/ttyUSB0 -b38400 -D -Uflash:w:blink.hex:i
But this is not an ATMega328P and there's nearly zero documentation on the web, I have a lot of questions and I'm not sure how to proceed.
To begin with, in man avrdude
, there's no mention of any Tiny0 or Tiny1 devices. What should the -p
argument be? Also, do I need to use a patched version of avrdude
? Do I need a customized avrdude.conf
? If so, where can I find them?