1

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?

asked Nov 7, 2020 at 22:32
1
  • Since you're using optiboot avrdude shouldn't care what the chip is. Commented Nov 7, 2020 at 22:58

1 Answer 1

2

After poking around in the git repository for a while, I've solved the problem. To work with these new TinyAVR-0/1 microcontrollers, a new version of avrdude is needed. Since avrdude hasn't made a stable release yet, it's necessary to build a new avrdude from source from SVN.

$ svn co https://svn.savannah.nongnu.org/svn/avrdude/trunk avrdude
$ cd avrdude/avrdude
$ ./bootstrap
$ mkdir build && cd build
$ ../configure
$ make
$ make install

After installation, /usr/local/bin/avrdude and /usr/local/etc/avrdude.conf should be available. One can see that a bunch of new TinyAVR parts have been added...

$ avrdude -p?
Valid parts are:
 [...]
 t10 = ATtiny10
 t11 = ATtiny11
 t12 = ATtiny12
 t13 = ATtiny13
 t15 = ATtiny15
 t1604 = ATtiny1604
 t1606 = ATtiny1606
 t1607 = ATtiny1607
 t1614 = ATtiny1614
 t1616 = ATtiny1616
 t1617 = ATtiny1617
 t1634 = ATtiny1634
 t20 = ATtiny20
 t202 = ATtiny202
 t204 = ATtiny204
 t212 = ATtiny212
 t214 = ATtiny214
 t2313 = ATtiny2313
 t24 = ATtiny24
 t25 = ATtiny25
 t26 = ATtiny26
 t261 = ATtiny261
 t28 = ATtiny28
 t3214 = ATtiny3214
 t3216 = ATtiny3216
 t3217 = ATtiny3217
 t4 = ATtiny4
 t40 = ATtiny40
 t402 = ATtiny402
 t404 = ATtiny404
 t406 = ATtiny406
 t412 = ATtiny412
 t414 = ATtiny414
 t416 = ATtiny416
 t417 = ATtiny417
 t4313 = ATtiny4313
 t43u = ATtiny43u
 t44 = ATtiny44
 t441 = ATtiny441
 t45 = ATtiny45
 t461 = ATtiny461
 t5 = ATtiny5
 t804 = ATtiny804
 t806 = ATtiny806
 t807 = ATtiny807
 t814 = ATtiny814
 t816 = ATtiny816
 t817 = ATtiny817
 t84 = ATtiny84
 t841 = ATtiny841
 t85 = ATtiny85
 t861 = ATtiny861
 t88 = ATtiny88
 t9 = ATtiny9
 [...]

To program the ATTiny1604, simply run...

$ avrdude -C/usr/local/etc/avrdude.conf -v -pt1604 \
 -carduino -P/dev/ttyUSB0 -b57600 -D -Uflash:w:blink.hex:i

Don't forget to modify the -b57600 argument to match the baud of your Optiboot_X build.

Lesson learned: When RTFM is impossible, use the source, Luke!

Potential Problems

avrdude: verification error; content mismatch

It's possible that avrdude successfully establishes communication with the board via the serial port, reads the correct device signature, then attempts to upload a program, but ultimately fails verification.

$ avrdude -v -pattiny1604 -carduino -P/dev/ttyUSB0 -b57600 -D -Uflash:w:blink.hex:i
Reading | ################################################## | 100% 0.00s
avrdude: Device signature = 0x1e9425 (probably t1604)
avrdude: reading input file "blink.hex"
avrdude: writing flash (204 bytes):
Writing | ################################################## | 100% 0.06s
avrdude: 204 bytes of flash written
avrdude: verifying flash memory against blink.hex:
avrdude: load data flash data from input file blink.hex:
avrdude: input file blink.hex contains 204 bytes
avrdude: reading on-chip flash data:
Reading | ################################################## | 100% 0.06s
avrdude: verifying ...
avrdude: verification error, first mismatch at byte 0x0000
 0x01 != 0x0c
avrdude: verification error; content mismatch

Solution: In TinyAVR 0/1, the bootloader is located at the beginning of the flash memory, occupies the first 512 bytes. When compiling the program to be uploaded via the bootloader, the correct 512-byte text section offset must be specified. Otherwise, avrdude will attempt to program from 0x00, which is impossible, because it's the location of the bootloader. Upon readback, instead of your program, avrdude reads the bootloader, which triggers the verification failure in question (it's worth noticing that 0x01, the first mismatched byte that triggers verification failure, is actually the first byte in the Optiboot_X binary code).

Instead of using...

avr-gcc -mmcu=attiny1604 -Wall -Os -o blink.elf blink.c

Recompile your program with `

avr-gcc -mmcu=attiny1604 -Wall -Os -o blink.elf blink.c \
-Wl,--section-start=.text=0x200
avr-objcopy -j .text -j .data -j .rodata -O ihex blink.elf blink.hex

And reupload it.

$ avrdude -v -pattiny1604 -carduino -P/dev/ttyUSB0 -b57600 -D -Uflash:w:blink.hex:i
avrdude: Device signature = 0x1e9425 (probably t1604)
avrdude: reading input file "blink.hex"
avrdude: writing flash (716 bytes):
Writing | ################################################## | 100% 0.00s
avrdude: 716 bytes of flash written
avrdude: verifying flash memory against blink.hex:
avrdude: load data flash data from input file blink.hex:
avrdude: input file blink.hex contains 716 bytes
avrdude: reading on-chip flash data:
Reading | ################################################## | 100% 0.00s
avrdude: verifying ...
avrdude: 716 bytes of flash verified
avrdude: safemode: Fuses OK (E:FF, H:FF, L:FF)
avrdude done. Thank you.

avrdude: programmer type jtagice3_updi not found

It's possible that avrdude reports the following error...

/usr/bin/avrdude -C/usr/local/etc/avrdude.conf -v -pattiny1604 -carduino -P/dev/ttyUSB0 -b38400 -D -Uflash:w:blink.hex:i
avrdude: Version 6.3, compiled on Jul 24 2019 at 00:00:00
 Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
 Copyright (c) 2007-2014 Joerg Wunsch
 System wide configuration file is "/usr/local/etc/avrdude.conf"
avrdude: error at "/usr/local/etc/avrdude.conf:1091: programmer type jtagice3_updi not found
avrdude: error reading system wide configuration file "/usr/local/etc/avrdude.conf"

Solution: You are trying to run an old version of avrdude with a new configuration file. Make sure the avrdude executable you are running is actually the up-to-date version compiled from the upstream SVN repository.

answered Nov 7, 2020 at 23:11

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.