stk500 avr atmega16 linux gcc hello, world

Does my title sound like buz-word central? You bet it does. That’s because it was a bit difficult to find any good introductory material on this. Maybe that’s because there’s so much information out there…

Anyway, here is some. The README:

Rich Lundeen
lundrich@isu.edu

The Specification:
———————————

The purpose of this assignment is to introduce you to the software tools we will use for the
AVR microprocessor, and to give you a better understanding of the run-time environment that
a C program operates under.
For this assignment, you will write a C main program and two subroutines – one in AVR
assembly, and the other in C. The subroutines should each do the same thing:
1. Monitor a port (your choice) that is connected to a switch. Wait until the switch is
pressed.
2. Once pressed, the routine should keep track of how long the switch is held down.
3. Wait for approximately one second.
4. Using another port (your choice) connected to a LED, turn on the LED for the same
amount of time that the switch was pressed earlier.
In addition to writing the code, determine the size of the code (main and both subroutines) in
your program.

———————————-

This code requires avrdude, avr-gcc, and objcopy are installed.

To compile the C version, type:

make

To compile the asm version, type:

make asm

After it’s compiled, to install to a connected and powered on atmega16 board, type:

make install

homework1.avi contains a short demonstration of the C version – however, both do the same thing. It
will play with vlc or mplayer.

Here is a demo of the program.. oooh blinky lights. Yeah, and anyway, the hardest part is just to find a hello world. This includes one in both C and assembly, so good hunting!

Download the source here,

/*main.c*/
#include "portstuff.h"

int main (void) {
  DDRB = 0xff;  /*11111111 means all output */
  DDRD = 0x00;  /*00000000 for all input */

  PORTB = 0xff;
  portmon();
  return(0);
}
/*portstuff.h*/
#include
#include
#include

void portmon();
/* portstuff.c */
#include "portstuff.h"

/*this is in clock cycles for my board.
* 30000 seems to be close to about a sec */
const DELAY = 30000;

void portmon() {
  while(1) {
    unsigned long timer = 0;
    unsigned long i;
    /*while a button is pressed */
    while (PIND != 0xff) {
      /*light up the button pressed */
      PORTB = PIND;
      timer += 1;
    }
    PORTB = 0xff;
    /*if the timer is not zero, we need to handle a button pressed */
    if (timer != 0) {
      /*delay for about a second */
      for (i = DELAY; i!=0; i--);
      PORTB = 0x00;
      /*delay for timer roughly equal to how long button was pressed */
      for (i = timer; i!=0; i--);
      timer = 0;
    }
  }
}
#Makefile
#c specific - this is the default

homework1.hex: homework1.out
    objcopy -S -O ihex homework1.out homework1.hex
homework1.out: main.o portstuff.o
    avr-gcc -mmcu=atmega16 main.o portstuff.o -o homework1.out
main.o: portstuff.h main.c
    avr-gcc -c -mmcu=atmega16 main.c
portstuff.o: portstuff.h portstuff.c
    avr-gcc -c -mmcu=atmega16 portstuff.c

#assembly specific rules

asm: howework1asm.out
    objcopy -S -O ihex homework1.out homework1.hex
howework1asm.out: main.o portstuffasm.o
    avr-gcc -mmcu=atmega16 main.o portstuffasm.o -o homework1.out
portstuffasm.o: portstuff.h portstuff.s
    avr-gcc -c -mmcu=atmega16 portstuff.s -o portstuffasm.o

#clean and install

clean:
    rm ./*.o ./*.hex ./homework1.out

install:
    avrdude -y -C /etc/avrdude/avrdude.conf -p atmega16 -P /dev/ttyS0 -c stk500v2 -U flash:w:homework1.hex:i
/*portstuff.s*/
#include "portstuff.h"

.file	"portstuff.c"
PORTB  = 56-0x20
PORTD  = 48-0x20
ALLON  = 31
WAIT   = 0xa
.text
.global	portmon
.type	portmon, @function
portmon:
/*initialize count to zero */
.BEGIN:
/*r18 is our counter*/
ldi     r18,0x00

/*initialize port values*/
in  r24,PORTD
out PORTB, r24

.LEDWAIT:
in  r24,PORTD
nop

/*see if the button is currently pressed - if it is then continue
if not jump to .LEDWAIT */
cpi r24, lo8(-1)
breq .LEDWAIT

.BUTTONPRESSED:

out PORTB, r24

/*measure the number of delays the button is pressed*/
rcall delay
inc r18

/*see if button is still currently pressed - if it is then
jump to Buttonpressed */

in   r24, PORTD
cpi  r24, lo8(-1)
brne .BUTTONPRESSED

out PORTB, r24
ldi r23, WAIT
.DELAYSECOND:
/*theoretically this delays a second */
rcall delay
dec r23
cpi r23,0
brne .DELAYSECOND

.LEDSON:
/*light up all leds for the amount of time the one was pressed*/
out PORTB, ALLON
rcall delay
dec r18
cpi r18,0
breq .BEGIN
rjmp .LEDSON

/*delay function makes time reasonable to deal with */
delay:
ldi r17,0x60
waitouterloop:
ldi r16,0xFF
waitinnerloop:
subi r16,0x01
brne waitinnerloop
subi r17,0x01
brne waitouterloop
ret

.size	portmon, .-portmon

2 Responses to stk500 avr atmega16 linux gcc hello, world

  1. mopey says:

    oh. this was for homework, which is where some of the terms come from.

  2. Danny Moules says:

    #
    # /*this is in clock cycles for my board.
    # * 30000 seems to be close to about a sec */
    # const DELAY = 30000;

    33333 more specifically.

    The chip will be running at 1000000 Mhz. That’s 1000000 cycles a second. Your delay routine takes 30 cycles to perform one iteration, thus the amount of times you need to iterate through the delay is roughly 33333 times.

    Thanks for the code!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s