I designed a custom AVR development board using the Atmel ATTiny1604 microcontroller. It belongs to the new Tiny-0 family, due to its recentness, some required changes to relevant toolchains have yet to be included into the stable version (I prefer to use the original upstream toolchains instead of Atmel/Microchip's SDK). Thus, I compiled the latest versions of toolchains from source. They include...
AVR GCC 10.2.0
avr-libc, svn trunk, with patch
avrxmega3-v10.diff
applied
After I installed the toolchains, I wrote a LED blinking program to verify whether my toolchain was working properly. The program was built with avr-gcc -mmcu=attiny1604 -Wall -Os -o blink.elf blink.c -Wl,--section-start=.text=0x200
and uploaded via the Optiboot_X bootloader.
#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);
}
}
However, I found that _delay_ms(500)
doesn't work as expected. Instead of a 500-millisecond delay, the actual delay is closer to 3000 milliseconds as seen on the oscilloscope, it has been slowed down by a factor of 6.
I've double-checked my fuse settings.
$ pyupdi -d tiny1604 -c /dev/ttyUSB0 -fr
Device info: {'family': 'tinyAVR', 'nvm': 'P:0', 'ocd': 'D:0', 'osc': '3', 'device_id': '1E9425', 'device_rev': '0.0'}
Fuse:Value
0:0x00
1:0x00
2:0x02
3:0xFF
4:0x00
5:0xF6
6:0x07
7:0x00
8:0x02
9:0xFF
10:0xC5
I saw pyupdi
reported that the fuse OSCCFG
(No. 2) has been programmed to 0x02
, which according to the datasheet, means "Run at 20 MHz with corresponding factory calibration". Why do I get incorrect delays even when the system clock is running at the correct speed? Is my toolchain broken?
Note: This is a question I already solved. But consider there are relatively few tutorials about the new TinyAVR 0/1 on the web, I posted the question and answer here to serve as a reference for the community.