This is a quick tutorial for beginners that aims to show how to install tools, compile the code with avr-gcc and send it to the MCU with avrdude. It also introduce basics of automation of this task by putting the all instructions into Makefile. The example files (main.c, main.bin, main.hex, Makefile) has been packaged as a .ZIP file and can be downloaded here.
Updates
[28.10.2019] Take a look at docker version of AVR Toolchain
1. Installing avr-gcc and tools
To compile C and/or C++ source code of your firmware you will need gcc-avr compiler, the avr-libc C library and avrdude. What is extremely useful, there are complete and easy to install packages for all major platforms.
Linux, Ubuntu
Ubuntu provides packages, so you can just install them using this command.
$ sudo apt-get install gcc-avr avr-libc avrdude
Mac OSX
Download AVR MacPack. The MacPack disk image has an installer that does everything for you.
Windows
Download WinAVR, which includes everything you need and has a nice installer.
2. Compiling and burning the code
Now that you have the compiler installed, a next step is to compile simple source code into a .BIN file, then generate Intel .HEX file and finally burn this .HEX file to AVR chip using USBasp programmer.
Example code
Here is an example content of main.c file. The code does nothing except getting stuck in an endless loop but it’s always something!
int main(void) { while (1); }
Compiling
The command below will compile your code. It’s GCC so I assume it looks familiar to you and no additional information is required. If you want perform compilation for some other MCU then you need specify appropriate -mmcu option.
$ avr-gcc -Wall -g -Os -mmcu=attiny13 -o main.bin main.c
After performing successful compilation, you can check program and data memory size with this command.
$ avr-size -C main.bin AVR Memory Usage ---------------- Device: Unknown Program: 40 bytes (.text + .data + .bootloader) Data: 0 bytes (.data + .bss + .noinit)
Generating .HEX
Most programmers will not accept a GNU executable as an input file, so we need to do a little more processing. So the next step is about converting the information form .BIN into .HEX file. The GNU utility that does this is called avr-objcopy.
$ avr-objcopy -j .text -j .data -O ihex main.bin main.hex
Burning
The utility called avrdude can program processors using the contents of the .HEX files specified on the command line. With the command below, the file main.hex will be burned into the flash memory. The -p attiny13 option lets avrdude know that we are operating on an ATtiny13 chip. In other words – this option specifies the device. The full list of supported parts can be found here. Note that full-length names are also acceptable (i.e. t13 equals attiny13).
$ avrdude -p attiny13 -c usbasp -U flash:w:main.hex:i -F -P usb
Voila! Chip is programmed.
3. Make and makefiles
Now, we can automate this process by creating a Makefile and putting our commands there. The structure of a Makefile is very simple, and more information about it can be found here. Utility make reads automatically a Makefile file in the folder where you launch it. Take a look at a ready-made example.
MCU=attiny13 F_CPU=1200000 CC=avr-gcc OBJCOPY=avr-objcopy CFLAGS=-std=c99 -Wall -g -Os -mmcu=${MCU} -DF_CPU=${F_CPU} -I. TARGET=main SRCS=main.c all: ${CC} ${CFLAGS} -o ${TARGET}.bin ${SRCS} ${OBJCOPY} -j .text -j .data -O ihex ${TARGET}.bin ${TARGET}.hex flash: avrdude -p ${MCU} -c usbasp -U flash:w:${TARGET}.hex:i -F -P usb clean: rm -f *.bin *.hex
If you launch a simple make in the terminal, only label “all” will be executed. When you launch (sudo) make flash label “flash” will be executed, and so on.
$ make avr-gcc -std=c99 -Wall -g -Os -mmcu=attiny13 -DF_CPU=1200000 -I. -o main.bin main.c avr-objcopy -j .text -j .data -O ihex main.bin main.hex $ make flash avrdude -p attiny13 -c usbasp -U flash:w:main.hex:i -F -P usb avrdude: warning: cannot set sck period. please check for usbasp firmware update. avrdude: AVR device initialized and ready to accept instructions Reading | ################################################## | 100% 0.00s avrdude: Device signature = 0x1e9007 avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed To disable this feature, specify the -D option. avrdude: erasing chip avrdude: warning: cannot set sck period. please check for usbasp firmware update. avrdude: reading input file "main.hex" avrdude: writing flash (40 bytes): Writing | ################################################## | 100% 0.05s avrdude: 40 bytes of flash written avrdude: verifying flash memory against main.hex: avrdude: load data flash data from input file main.hex: avrdude: input file main.hex contains 40 bytes avrdude: reading on-chip flash data: Reading | ################################################## | 100% 0.03s avrdude: verifying ... avrdude: 40 bytes of flash verified avrdude: safemode: Fuses OK (H:FF, E:FF, L:6A) avrdude done. Thank you.
4. Summary
Essentially, assuming that our program is in main.c, only those three things are needed to compile and burn the code to AVR chip.
$ avr-gcc -Wall -g -Os -mmcu=attiny13 -o main.bin main.c $ avr-objcopy -j .text -j .data -O ihex main.bin main.hex $ avrdude -p attiny13 -c usbasp -U flash:w:main.hex:i -F -P usb
It’s important to highlight that we can easily automate whole process with Makefiles. Sooner or later you will need it!
Hi Łukasz, excellent description. I was just about to write one for my students and got stuck at one point until I found yours. Now I mangled both and sent it to my boys and girls under your and my name, including a translation into German. I hope that it is ok for you….I am using mainly atmega88 and a selfmade STK500 clone. It also works from a virtual linux (Ubuntu 20.04.2 on an Oracle Virtual Box VM) which does not make much sense but even that works fine.
Ansgar
Hi, I’m glad I could help. Sure, it’s fine.
/LP
Hi Łukasz can you add an attention next to the WinAVR option because instead of appending to sytem path it just overwrites on it and now my system path is gone. Hope this helps newcomers.
this exelent
Hey, thanks a lot for this, its super useful for a beginner like me.
I had to set fuses with avrdude -U lfuse:w:0x6A:m […], so the frequences were correct, my attiny13a had different defaults probably.
The frequency is still a tiny bit off, is that normal?
Hi Lukasz, firstly many thanks for this. I have not done something like this before and so I am just working through this page step by step to see what happens. I downloaded “034_rainbow_on_single_led_ws2812” and then from within that folder ran
avr-gcc -Wall -g -Os -mmcu=attiny13 -o main.bin main.c
The result was
In file included from main.c:8:
/usr/avr/include/util/delay.h:92:3: warning: #warning “F_CPU not defined for ” [-Wcpp]
92 | # warning “F_CPU not defined for ”
| ^~~~~~~
/usr/lib/gcc/avr/9.2.0/../../../../avr/bin/ld: /tmp/cckCbTmF.o: in function `main’:
/home/abasel/Dropbox/Transfer/WorkingOn/Night-Light/Podkalicki/blog-master/avr/attiny13/034_rainbow_on_single_led_ws2812/main.c:36: undefined reference to `ws2812_setleds’
collect2: error: ld returned 1 exit status
What am I doing wrong or missing?
Absolutely essential tutorial. Everything what I (and probably others either) need. Simple, clear and quick.
10/10 for the author!
Thanks Jakub! If you use linux and you like docker then please take a look at this solution – https://hub.docker.com/r/lpodkalicki/avr-toolchain
/L
I have programmed ATTinys with the Arduino IDE before and with success, but when I put your firmware for the ATtiny13 IR remote control of LEDS in my Arduino IDE and check the code, it gives me the following error:
sketch_aug22a:51:9: error: ‘void IR_init()’ was declared ‘extern’ and later ‘static’ [-fpermissive]
IR_init()
Obviously, I’m doing something wrong, can you help?
The settings in the Arduino IDE are: ATTiny13, 9.6MHz, BOD disabled, LTO enabled (default)
I am beginner in this so please help. Thanks!
I’m not using arudino as a programmer but I have a tip for all my code examples used by Arduino IDE – change file extensions *.c to *.cpp to make the compiler and linker know what sources they need to use.
Hi Lukasz, Thanks for your suggestion, but unfortunately I could not get it to work. Same error keeps coming up.
Wow, this tutorial was unique and extraordinary, no where I could solve my problems while working with gcc-avr like here. Thanks a ton!
thank you very much, a very helpful document, I have been able to burn a program to my ATtiny13a
Great! Thanks Robert for leaving a comment. I’m sure it will serve here as a nice recommendation for other readers.
/LP
Hey, Thanks for the instruction on Makefiles, I’m temporarily stuck using my Linux box while the other one is in the shop. Your file had the basics that I needed to produce a Hex file. I never used just avr – gcc and a makefile but figured it’s time. Feeling naked without my assembler, simulator and windoze.
Thanks
Hey, thanks 🙂 Makefile helps automate whole proces on unix-like systems, a lot.
Hi Łukasz! But how would I do that? I already have the files ready, downloaded from the internet, including the Makefile as here: https://github.com/WiseLord/hub08lib
Could you give me a hint how to write this code on atmega328p the easy way?
Thanks ++
Hi, for that code (see: https://github.com/WiseLord/hub08lib/blob/master/Makefile) you need some basic tools like USBasp programmer and AVR toolchain. In the article above I included information how to prepare the development environment to make it work. Hope it will help!
/L
First, thanks for the tutorial!
Is there no other way to write to the AVR chip without using the USBasp programmer?
Say, use the Arduino IDE as a programmer? Thank you
There is few ways to make it happen. It mostly depend on chip ID and user choice. One way is to use build-in protocol and other way is to use bootloader – i.e. from Arduino.
ir_receiver_38khz_nec_proto_analyzer
Hex
HI,
I am getting an error while uploading it using the avrdude
avrdude: error: program enable: target doesn’t answer. 1
avrdude: initialization failed, rc=-1
avrdude: AVR device initialized and ready to accept instructions
avrdude: Device signature = 0x88dbe5
avrdude: Expected signature for ATmega328P is 1E 95 0F
avrdude: NOTE: “flash” memory has been specified, an erase cycle will be performed
To disable this feature, specify the -D option.
avrdude done. Thank you.
It would be really nice if you could help me with it.
Hi, unfortunately a lot of things could happen here: