The Arduino IDE is great for being able to dive right in and spin up a sketch quickly with a minimum of fuss. However, there are some situations where you want to get a little “closer to the metal” – without some of the limitations that come with that ease-of-use. Maybe you want to use a program or library that’s been created for AVR GCC or Atmel Studio. Here’s how to get a working build environment up and running on an Linux system quickly and easily.
For this walk-through, we’ll be targeting the ATmega32u4 in an Arduino Pro Micro – the same board that we used in the Macro Keypad project. This should work regardless if you have a real Arduino or one of the cheap Chinese clone boards that you can get off of eBay for a few dollars. These boards are great if you want to interact via the USB port to act as a keyboard, mouse, or MIDI source/receiver.
The first thing you need to do is install the AVR GCC and AVRDUDE utilities:
sudo apt-get install binutils gcc-avr avr-libc uisp avrdude flex byacc bison
Create a new folder, maybe something like home/avr/blink. Navigate to the new folder and create a new blink.c file in your favorite text editor.
#ifndef F_CPU
#define F_CPU 16000000UL // or whatever may be your frequency
#endif
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
DDRB = 0xFF; // set all PORTB pins to output
while(1)
{
// LED on
PORTB = 0xFF; // Turn on all PBx pins
_delay_ms(500); // wait 500 milliseconds
//LED off
PORTB = 0x00; // Turn off all PBx pins
_delay_ms(500); // wait 500 milliseconds
}
}
Then create a new build file and save it as build_script:
avr-gcc -g -Os -mmcu=atmega32u4 -c blink.c
avr-gcc -g -mmcu=atmega32u4 -o blink.elf blink.o
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex
avr-size --format=avr --mcu=atmega32u4 blink.elf
Again, this assumes you are targeting an ATmega32u4 controller, so adjust as needed if you’re using a different chip. Then make sure that the script has execute permissions:
sudo chmod 755 build_script
To compile and build your program, just execute the script:
./build_script
You should see a little output that looks like this:
AVR Memory Usage
----------------
Device: atmega32u4
Program: 246 bytes (0.8% Full)
(.text + .data + .bootloader)
Data: 0 bytes (0.0% Full)
(.data + .bss + .noinit)
Now, if your Pro Micro may or may not have a small momentary button on it. If it does, this normally connects the RST (reset) pin to ground and puts the ATmega32u4 into Device Firmware Update (DFU) mode. If your board does not have a button, you’ll need to add one with a 10k pullup resistor. Most of the time, though, you can get away with just using a jumper wire connecting RST to GND.
If you haven’t already done so, connect your board via USB and verify that the power light comes on. Then push the button or ground the RST pin, release it, and run AVRDUDE to flash the hex file to your controller:
avrdude -v -c avr109 -p atmega32u4 -P /dev/ttyACM0 -b 57600 -D -U flash:w:blink.hex
You only have about 8 seconds to upload the hex file after resetting the board, so it’s handy to have the avrdude command ready to go in your terminal window first. Assuming that you’ve done everything correctly, you should see something like:
avrdude: Version 6.3-20171130
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
Copyright (c) 2007-2014 Joerg Wunsch
System wide configuration file is "/etc/avrdude.conf"
User configuration file is "/home/digitorus/.avrduderc"
User configuration file does not exist or is not a regular file, skipping
Using Port : /dev/ttyACM0
Using Programmer : avr109
Overriding Baud Rate : 57600
AVR Part : ATmega32U4
Chip Erase delay : 9000 us
PAGEL : PD7
BS2 : PA0
RESET disposition : dedicated
RETRY pulse : SCK
serial program mode : yes
parallel program mode : yes
Timeout : 200
StabDelay : 100
CmdexeDelay : 25
SyncLoops : 32
ByteDelay : 0
PollIndex : 3
PollValue : 0x53
Memory Detail :
Block Poll Page Polled
Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
eeprom 65 20 4 0 no 1024 4 0 9000 9000 0x00 0x00
flash 65 6 128 0 yes 32768 128 256 4500 4500 0x00 0x00
lfuse 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00
hfuse 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00
efuse 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00
lock 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00
calibration 0 0 0 0 no 1 0 0 0 0 0x00 0x00
signature 0 0 0 0 no 3 0 0 0 0 0x00 0x00
Programmer Type : butterfly
Description : Atmel AppNote AVR109 Boot Loader
Connecting to programmer: .
Found programmer: Id = "CATERIN"; type = S
Software Version = 1.0; No Hardware Version given.
Programmer supports auto addr increment.
Programmer supports buffered memory access with buffersize=128 bytes.
Programmer supports the following devices:
Device code: 0x44
avrdude: devcode selected: 0x44
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.00s
avrdude: Device signature = 0x1e9587 (probably m32u4)
avrdude: safemode: lfuse reads as FF
avrdude: safemode: hfuse reads as D8
avrdude: safemode: efuse reads as CB
avrdude: reading input file "led.hex"
avrdude: input file led.hex auto detected as Intel Hex
avrdude: writing flash (246 bytes):
Writing | ################################################## | 100% 0.02s
avrdude: 246 bytes of flash written
avrdude: verifying flash memory against led.hex:
avrdude: load data flash data from input file led.hex:
avrdude: input file led.hex auto detected as Intel Hex
avrdude: input file led.hex contains 246 bytes
avrdude: reading on-chip flash data:
Reading | ################################################## | 100% 0.00s
avrdude: verifying ...
avrdude: 246 bytes of flash verified
avrdude: safemode: lfuse reads as FF
avrdude: safemode: hfuse reads as D8
avrdude: safemode: efuse reads as CB
avrdude: safemode: Fuses OK (E:CB, H:D8, L:FF)
avrdude done. Thank you.
Depending on your board, the built-in light may start blinking at this point. If not, just hook up an LED with a suitable current-limiting resistor to one of the PORTB pins. On my board, I used physical pin 16.
Troubleshooting
Your board may show up on a different port. If you’re not sure what port it is on, you can see a list of candidates using the ls command. Your board will probably be something like ttyACM0 or ttyUSB0.
ls /dev/tty*
You may see an error like this during the flashing operation:
avrdude: stk500_recv(): programmer is not responding
This normally means that the chip is not in update mode. If your board has a button, make sure you are fully depressing it. Try shorting the RST using a (different) jumper wire.