Tuesday, December 2, 2014

Starting Assembly With AVRA

Introduction

The Arduino platform is very popular. The UNO in particular has made qute a splash. I have been using them myself for quite some time. The IDE is easy to set up and use, and anyone who has any experience with C/C++ can get a working sketch up and running without too much fuss. For anyone who wants to get into the realm of programming microcontrollers this would be an excellent place to start.

I however, am old-school. When it comes to microcontrollers I still prefer assembly and I like knowing what's working behind the scenes and how to extract as much horsepower out of that little slab of silicon as I can. Either that or I just like to torture myself, you decide.

I've searched the internet for sites related to assembly on the AVR devices and have noticed that there isn't much out there. Not a lot of information or assemblers for that matter. Atmel's studio which I have not used for quite some time is quite capable of creating an assembly program but is geared much more tword C/C++.

There's also GNU's avr-as which comes as part of the Arduino IDE. This I have used but requires the extra step of extracing your program from an .elf file after compiling.

After a while I stumbled upon AVRA. This as it turns out was exactly what I was looking for. Take assembly mneumonics and convert them to machine code. Don't try to anticipate what I want, just do what I tell you (old-school remember?).

Installing AVRA

I use Ubuntu 14.04. Installing avra is pretty simple since it's already part of the Ubuntu repository. To install the assembler on your system, use the Synaptic Package Manager and do a search for avra. Mark avra for installation and Apply. AVRA is a command line assembler, so if your looking for an IDE you won't find one.

Invoking the assembler

To run the compiler you first need to open a command terminal. If your using Ubuntu, Ctrl-Alt-T will do the trick otherwise you can use Terminal or LXTerminal from the desktop menu. From within the terminal window type 'avra' (without the quotes) and you should be greeted with a brief explanation of the different command line options available.

If everything has been successful to this point then it's time to write and compile your first assembly program for an AVR microcontroller. We'll be using the Arduino Uno which has an atmega328p device and hopefully you have the Arduino IDE installed as well because we will be using 'avrdude' to upload our program to the device.

The Beginning - Blink.asm

Experience with every hardware platform starts the same way. Can we get the tool-chain to work? So in true 'Hello World' fashion we are going to get the on-board LED connected to pin #13 to flash and hopefully get you comfortable with assembling and transfering programs to the device.

Using your favorite text editor, enter the following code. I use Atom but gedit or any other editor that saves files in plain text will do. Save the file as 'blink.asm'.


          .device atmega328p

          .equ RAMEND = 0x8ff   ;End of user RAM
          .equ SREG = 0x3f      ;Status Register
          .equ SPL = 0x3d       ;Stack Pointer Low
          .equ SPH = 0x3e       ;Stack Pointer High
          .equ PORTB = 0x05     ;Port B
          .equ DDRB = 0x04      ;Data Direction Register Port B

          ;Reset Vector
          .org 0x0000
             rjmp main

          ;Main Program Start
          .org 0x003a
          main:
             ldi r16,0            ;reset system status
             out SREG,r16         ;init stack pointer
             ldi r16,low(RAMEND)  ;0xff
             out SPL,r16
             ldi r16,high(RAMEND) ;0x08
             out SPH,r16

             ldi r16,0x20         ;set port PB5 to output mode
             out DDRB,r16

             clr r17
          mainloop:
             eor r17,r16          ;invert output bit
             out PORTB,r17        ;write to port
             call wait            ;wait some time
             rjmp mainloop        ;loop forever

          wait:
             push r16
             push r17
             push r18

             ldi r16,0x20         ;loop 0x400000 times
             ldi r17,0x00         ;~12 million cycles
             ldi r18,0x00         ;~0.7s at 16Mhz
          w0:
             dec r18
             brne w0
             dec r17
             brne w0
             dec r16
             brne w0

             pop r18
             pop r17
             pop r16
             ret
        

Now that you have the source file, go to the terminal window and change the directory to the folder where you saved your file. For me it's under ~/Documents/assembly/blink. For you I'm sure it will be different. Once there enter the following command:

avra blink.asm

If everything goes ok, which it should, you will see something like the following...

Issue the ls -l command and you'll notice that avra generated four other files from your one blink.asm. The one we are interested in is blink.hex. This is the one we are going to send to the Arduino Uno using avrdude. If you open the hex file in your text editor you'll see there really isn't that much there. It's just a series of hexadecimal numbers that will be loaded into the device's program memory by the bootloader. In fact, lets do that.

First off, you need to know where the serial port to the Arduino is. On my system it is at

/dev/ttyACM0

If your not sure, issue this command at the command prompt -> dmesg | grep tty. This will list all the serial ports on your system. If your not sure which one it is, run the command with the Arduino plugged in and one where it is not. The missing port will be the one your looking for.

So finally, lets get the program into the device.

avrdude -patmega328p -carduino -P/dev/ttyACM0 -b115200 -Uflash:w:"blink.hex":i

A little explanation of the options:

            -p The AVR device. The Uno has an atmega328p
            -c The programmer type. In this case it's an arduino
            -P Specify the port. /dev/ttyACM0 here, yours might be different
            -b Baud rate
            -U The memory type, file and format to use.
               We will be writing to flash memory using blink.hex
               which is in intel hex format.
            

Once finished, the device will reset and you should have an LED blinking away on your Arduino Uno.

No comments:

Post a Comment