Friday, July 16, 2010

AVR1

It is my firm belief that anyone starting
out to learn to program a new processor should start
with its assembly language. My reasoning is that using assembly
forces you to learn and understand the architecture
of the processor. To be any good at assembly you must
be able to hold an image of the chip's hardware in your mind. You must
know exactly where the data is, what the assembly instructions
do with that data and how your code controls the hardware.
In short, if you want to do really good work then you had
better know how to code in assembler(asm).

Luckily assembler is the simplest of all languages to code
in. Now I did not mean it is the fastest way to write code
for a processor, just that it is the simplest and most
elementary way. Most processors have a relatively small collection
of assembly instructions and these are nearly all as easy
to understand as 1 + 1 = 2. The AVR and the MSP430 are easy to
program in assembly and the Parallax Propeller processor(the Prop)
is no exception, it too is easy to program in asm!

The easiest way to learn asm is by taking short asm programs
that are already written and known to work and making modifications
to them. We will start with the simplest of all asm programs, one
that does absolutely nothing! It is what is called a program template.
You will use such a template over and over, it saves you
from having to re enter all the preliminary stuff. Never start
an asm program from scratch, that is a waste of your time.

Here is a suitable program template for the AVR.
It is very basic and later I will create a more
complete version that sets up the stack address
and has place holders for interrupt routines.etc.


; ********************************************
; * Put program name here along with date                   *
; * written and any other pertinent info                         *
; ********************************************

.NOLIST
.INCLUDE "tn85def.inc"
.LIST

rjmp Start ; This is the reset vector


Start:
rjmp Start ; loop 4ever


Here is what this short program looks like in AVR Studio
when it is compiled.

This image shows how much memory has been used
by this short program. It only takes up 4 bytes of the
8192 bytes available in the Tiny85's flash memory.
Of course it doesn't actually do anything...it just causes
the AVR to continually execute the first instruction
that is located at the label Start: this is an identical rjmp
instruction that causes the program counter to load the
location of  Start:  and jump there....an infinite loop.
 When powered up the Tiny85 will execute the instruction
it finds at memory location zero (the reset interrupt vector
location) it finds an instruction there that loads the program
counter with the location of the Start: label    when the
Tiny85 gets to that location it finds another instruction
that simply points it again at the location of the Start:
label.



Start:    
rjmp Start

This simple program can actually be made smaller.
This works just as well.

; ********************************************
; * Put program name here along with date    *
; * written and any other pertinent info     *
; ********************************************

.NOLIST
.INCLUDE "tn85def.inc"
.LIST

Start:
    rjmp Start ; loop 4ever

This version uses only 2 bytes. But there is a very
good reason to include this line

rjmp Start ; This is the reset vector

The reason is that in the AVR the interrupt vectors
are all in low memory starting at location 0x000000
This first vector is called the reset vector and it is
the first instruction that is run whenever the Tiny85
is powered up or reset. It is best to place an rjmp
instruction here and jump to the start of your asm
program. You may need to come back and add some
rjmp instructions that point to a routine you wish to run
when another of the interrupts is triggered. The locations
that are meant to hold the vectors can be used for regular
program code as long as the interrupts will never be called!

Here is the interrupt chart from  the Tiny85 datasheet
Some people just add them all as sort of placeholders
whether they use them all or not...like this

    rjmp Start ; Reset vector
    reti ; Int vector 1
    reti ; Int vector 2
    reti ; Int vector 3
    reti ; Int vector 4
    reti ; Int vector 5
    reti ; Int vector 6
    reti ; Int vector 7
    reti ; Int vector 8
    reti ; Int vector 9
    reti ; Int vector 10
    reti ; Int vector 11
    reti ; Int vector 12
    reti ; Int vector 13
    reti ; Int vector 14

This takes up space that could be used by program
code, unless you need to use all 14 interrupts..this
is rarely the case. But some people just like to start
out with a list like this. If any interrupts are triggered
they jump to the corresponding reti (return from interrupt)
command and all is well. You can simply replace one
of the lines above with an rjmp command to cause
your code to be jumped to if a particular interrupt is
triggered...like so

reti ; Int vector 5

might be replaced by

rjmp MyTimer1OverflowCode


Here is the program with all the placeholders for
the interrupt vectors added.







This works just fine
but note that the memory usage is now at 32 bytes!





Now, probably it won't matter if you use up a few
extra bytes but I prefer to keep things trim. You
must be careful though to place a vector into the
proper location if you do not use placeholders and
later want to edit your asm and add an rjmp to a
new interrupt routine! You can use the org command to
make certain of where you place an interrupt vector.
This will place a new rjmp at the proper location
for interrupt 3, the pin change interrupt. (remember
that the memory is counted up from zero so the third
location is at $0002)

.ORG $0002
rjmp MyPinChangeCode









This entire program with the new int vector
for the pin change interrupt and the tiny
MyPinChange routine is only 8 bytes. Using
the .ORG moves your code that begins at Start:
farther up in memory so you are leaving some
bytes unused.

I think I will use the template version with the full
list of interrupt vector place holders for the time being.
I think it will be easier for newbies to understand with
them listed. Just be aware that once you get used to AVR
asm you don't have to do it this way. Just always remember
where these important vectors are in memory! The number
of interrupt vectors is different for different AVRs ..just
check the data sheet to see what and where they are.



More later...stay tuned :-)

No comments:

Post a Comment