Introduction
Hey, you must be fimilier with the classic Arduino Uno. This was my first ever microcontroller board and frankly the most used one too, I loved it. But first what is Arduino software stack, Arduino is a abstraction layer on top of the baremetal AVR utilities. This abstraction layer makes things so easy that even a highscool kid can learn microcontroller programming and make stuff out of it. This comes at a cost, you are restricted with the arduino framework, design pattern, the arduino IDE. To make things easy, arduino framework hides lot of features and configuration is provided in the MCU. If you want to be a good embedded engineer you cant stay with Arduino framework forever.
So now its time to level up. Lets understand how can we program our arduino board without the arduino software framework:
- Writing raw C code with standered
int main()
function and compile ourself with theavr-gcc
compiler. - Operating the peripherals by manupulating registers with bitwise operations.
- Flasing the code using the
avrdude
utility. - (Optional) Get rid of the arduino bootloader and use external programmers.
Toolchain installation
Linux
# Arch Linux
sudo pacman -S avr-gcc avr-libc avrdude avr-gdb avr-binutils
# Ubuntu
sudo apt-get install gcc-avr binutils-avr avr-libc gdb-avr avrdude
# Fedora
sudo dnf install avr-binutils avr-gcc avr-gcc-c++ avr-libc avrdude
Windows
For windows you can install WinAVR
which is collection of tools for AVR.
MacOS
For mac checkout. hohmebrew-avr
Hello world
Now that you have the avr toolchain installed, its time to write a simple program, compile and flash on to the microcontroller. Create a new directory with a file main.c
and write following code in it.
int main(){
while();
}
This is a very minimal code to be compiled and flashed on to the microcontroller. Lets compile it using avr-gcc
. The arguments for avr-gcc
is pretty much like standered gcc
compiler, we just have to give extra flag -mmcu
which tells the compiler what microcontroller we are using, in our case Arduino Uno has the ATmega328P
mcu.
avr-gcc -mmcu=atmega328p main.c -o main.elf
The elf
file is to be converted to a hex
format which will be flashed on to the microcontroller. We will use the avr-objcopy
utility which will converted the elf
to ihex
(Intex Hex) format. The -O
flag set the output format which is ihex
in this case. -R .eeprom
which remove the eeprom section from the final hex file.
avr-objcopy -O ihex -R .eeprom main.elf main.hex
Uploading code
Now that we have the firmware to be flashed onto the microcontroller, we have two methods(There are more, but these two are most common).
Arduino bootloader
The Arduino bootloader is a small program pre-installed on Arduino boards, allowing easy uploading of code via USB without requiring an external programmer, by handling serial communication and program flashing. To flash the code we will use the avrdude
utility. To flash through serial we need to know what serial port the Arduino uno is connected, for that I have nice utility called lsserial
which is a python script to print info about all the serial devices connected to the computer.
avrdude -F -c arduino -p atmega328p -P /dev/ttyACM0 -b 115200 -U flash:w:main.hex
Lets examine the avrdude flags:
-F
This flag is to disable mcu signature matching, every avr board has some signature egDevice signature = 1E 95 16 (ATmega328PB)
and if your Arduino board may be using some different varient of Atmega32 mcu, it will abort the upload. We will see how to correctly find which mcu we are using later.-c
This flas is used to specify what programmer we are using, in this case the arduino bootloader.-p
We specify what mcu we intend to flash, for now we are using the standered atmega328p for Arduino uno.-P
Here we specify the serial port Arduino is connected to, you can find that using thelsserial
utility-b
The baud rate for the serial data line-U
This is used to carry out any kind of memory operation, here we specify the hex file to be flashed. We will discuss this in detail later.
In-circuit serial programming(ICSP)
AVR ICSP (In-Circuit Serial Programming) is a method used to program AVR microcontrollers directly on a circuit without removing them. It uses the SPI interface (MISO, MOSI, SCK) to upload firmware, enabling faster and more efficient development and debugging.
I highly recommend using external ICSP programmer. Here are list of reasons which makes ICSP programmer better than arduino bootloader:
- Allows programming of fuse bits.
- Works without pre-loaded bootloader.
- Faster than bootloader-based uploads.
There are many ICSP programmer, I am going to use the USBasp
and you can get one too for under $10. Finally you can make use of the ICSP Pin header in arduino board.
If you dont want to manual wiring, you can get a
AVR-ISP 10Pin to 6pin Adapter
Now lets finally upload the code, this is the command for that. The only change is the -c
flag as we are using usbasp
avrdude -F -c usbasp -p atmega328p -U flash:w:main.hex
If you see output like this, congrats!!!! You just progrmmed your Arduino uno without the Arduino IDE.
Writing 166 bytes to flash
Writing | ################################################## | 100% 0.23 s
Reading | ################################################## | 100% 0.13 s
166 bytes of flash verified