Getting started with programming of the Atmel AVR

News Site news RSS

Latest articles New articles RSS

Latest news from Twitter Follow Secretkeeper4 and www.svesoftware.com on Twitter

Getting started with programming of the Atmel AVR

Everything written regarding installation of packages is based on OpenSuSE 13.1 distribution.

Software requirements

We need simulator of AVR, simulavr package.

#> zypper install simulavr

Later, we will need to upload HEX code into AVR, using avrdude.

#> zypper install avrdude

Then we need cross compiler for avr, which is package cross-avr-gcc.

http://software.opensuse.org/ymp/CrossToolchain:avr/openSUSE_13.1/cross-avr-gcc.ymp?base=openSUSE%3A13.1&query=cross-avr-gcc

This is 1-click install for OpenSuSE 13.1. It will add additional repository CrossToolchain:avr.

You can debug using avr-gdb, or using cross-avr-insight package (avr-insight), but later is a little buggy for me. I am aiming for ATTINY85, so here is a little helloworld.c program:

#ifndef F_CPU
#define F_CPU 20000000L
#endif
 
#include <avr/io.h>
#include <util/delay.h>
 
#define LED PB0 // Define ext led pin on PB0 *2
 
int main(void)
{
  DDRB |= (1 << LED); // Set output direction on LED (PB0) *2
  int delay = 1000;
  int i = 0;
 
  while (1) {
    PORTB &= ~(1 << LED); // Set 0 on LED pin (led turn on)
    for(i = 0; i < delay; i++) {
      _delay_ms(10); // Call delay for 300 milisec
    }
    PORTB |= (1 << LED); // Set 1 on LED pin (led turn off)
    for(i = 0; i < delay; i++) {
      _delay_ms(10); // Call delay for 300 milisec
    }
  }
 
  return 0;
}

This program should blink LED diode in endless loop. Notice that we can't use bigger delays using _delay_ms funcion because of limitations explained in util/delay.h.

Here is a simple script which should compile helloworld.c in .elf format.
 
rm helloworld.o helloworld.elf
avr-gcc -gdwarf-2 -Wall -Os -Werror -Wextra -mmcu=attiny85 -mtiny-stack -fno-zero-initialized-in-bss -c -o helloworld.o helloworld.c
avr-gcc -gdwarf-2 -Os -Werror -Wextra -mmcu=attiny85 -mtiny-stack -fno-zero-initialized-in-bss -o helloworld.elf helloworld.o
 
Next, run simulavr:
simulavr -d attiny85 --file helloworld.elf -s -g -F 20000000
 
dnezic@svecomp11:/storage/users/dnezic/development/avr> simulavr -d attiny85 --file helloworld.elf -s -g -F 20000000
Waiting on port 1212 for gdb client to connect...
 
 
Start avr-gdb:
dnezic@svecomp11:/storage/users/dnezic/development/avr> avr-gdb
GNU gdb (GDB) 7.5.1
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-suse-linux-gnu --target=avr".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
(gdb) 
 
 
Connect to simulavr on port 1212.
 
(gdb) target remote localhost:1212
Remote debugging using localhost:1212
warning: Can not parse XML target description; XML support was disabled at compile time
0x00000000 in ?? ()
 
Load .elf in gdb
 
(gdb) file helloworld.elf 
A program is being debugged already.
Are you sure you want to change the file? (y or n) y
Reading symbols from /storage/users/dnezic/development/avr/helloworld.elf...done.
 
Transfer program in simulavr:
(gdb) load
Loading section .text, size 0x74 lma 0x0
Start address 0x0, load size 116
Transfer rate: 928 bits in <1 sec, 116 bytes/write.
 
Disassemble main function:
 
(gdb) disas main
Dump of assembler code for function main:
   0x00000030 <+0>:     sbi     0x17, 0 ; 23
   0x00000032 <+2>:     ldi     r24, 0x87       ; 135
   0x00000034 <+4>:     ldi     r25, 0x13       ; 19
   0x00000036 <+6>:     sbiw    r24, 0x01       ; 1
   0x00000038 <+8>:     brne    .-4             ;  0x36 <main+6>
   0x0000003a <+10>:    rjmp    .+0             ;  0x3c <main+12>
   0x0000003c <+12>:    nop
   0x0000003e <+14>:    cbi     0x18, 0 ; 24
   0x00000040 <+16>:    ldi     r24, 0xE8       ; 232
   0x00000042 <+18>:    ldi     r25, 0x03       ; 3
   0x00000044 <+20>:    ldi     r30, 0x4F       ; 79
   0x00000046 <+22>:    ldi     r31, 0xC3       ; 195
   0x00000048 <+24>:    sbiw    r30, 0x01       ; 1
   0x0000004a <+26>:    brne    .-4             ;  0x48 <main+24>
   0x0000004c <+28>:    rjmp    .+0             ;  0x4e <main+30>
   0x0000004e <+30>:    nop
   0x00000050 <+32>:    sbiw    r24, 0x01       ; 1
   0x00000052 <+34>:    sbiw    r24, 0x00       ; 0
   0x00000054 <+36>:    brne    .-18            ;  0x44 <main+20>
   0x00000056 <+38>:    sbi     0x18, 0 ; 24
   0x00000058 <+40>:    ldi     r24, 0xE8       ; 232
   0x0000005a <+42>:    ldi     r25, 0x03       ; 3
   0x0000005c <+44>:    ldi     r30, 0x4F       ; 79
   0x0000005e <+46>:    ldi     r31, 0xC3       ; 195
   0x00000060 <+48>:    sbiw    r30, 0x01       ; 1
   0x00000062 <+50>:    brne    .-4             ;  0x60 <main+48>
   0x00000064 <+52>:    rjmp    .+0             ;  0x66 <main+54>
   0x00000066 <+54>:    nop
   0x00000068 <+56>:    sbiw    r24, 0x01       ; 1
   0x0000006a <+58>:    sbiw    r24, 0x00       ; 0
   0x0000006c <+60>:    brne    .-18            ;  0x5c <main+44>
   0x0000006e <+62>:    rjmp    .-50            ;  0x3e <main+14>
End of assembler dump.
(gdb) 
 
Trace:
 
(gdb) step
Single stepping until exit from function __vectors,
which has no line number information.
0x0000001e in __trampolines_start ()
(gdb) step
Single stepping until exit from function __trampolines_start,
which has no line number information.
main () at helloworld.c:14
14               DDRB |= (1 << LED); // Set output direction on LED (PB0) *2
 
... or instruction by instruction:
 
(gdb) stepi
0x00000054      20                  for(i = 0; i < delay; i++) {
(gdb) stepi
_delay_ms (__ms=10) at /opt/cross/avr/avr/include/util/delay.h:164
164             __builtin_avr_delay_cycles(__ticks_dc);
(gdb) stepi
0x00000046      164             __builtin_avr_delay_cycles(__ticks_dc);
 
Various commands:
(gdb) info all-registers
r0             0xaa     170
r1             0x0      0
r2             0xaa     170
r3             0xaa     170
r4             0xaa     170
r5             0xaa     170
r6             0xaa     170
r7             0xaa     170
r8             0xaa     170
r9             0xaa     170
r10            0xaa     170
r11            0xaa     170
r12            0xaa     170
r13            0xaa     170
r14            0xaa     170
r15            0xaa     170
r16            0xaa     170
r17            0xaa     170
r18            0xaa     170
r19            0xaa     170
r20            0xaa     170
r21            0xaa     170
r22            0xaa     170
r23            0xaa     170
r24            0xe6     230
r25            0x3      3
r26            0xaa     170
r27            0xaa     170
r28            0x5f     95
r29            0x2      2
r30            0x4f     79
r31            0xc3     195
SREG           0x0      0
SP             0x80025d 0x80025d
PC2            0x48     72
pc             0x48     0x48 <main+24>
 
Look for pc and sp registers.
 
Other commands:
 
(gdb) info target
Symbols from "/storage/users/dnezic/development/avr/helloworld.elf".
Remote serial target in gdb-specific protocol:
Debugging a target over a serial line.
        While running this, GDB does not access memory from...
Local exec file:
        `/storage/users/dnezic/development/avr/helloworld.elf', file type elf32-avr.
        Entry point: 0x0
        0x00000000 - 0x00000074 is .text
        0x00800060 - 0x00800060 is .data
 
(gdb) info program
Debugging a target over a serial line.
Program stopped at 0x48.
It stopped after being stepped.
 
(gdb) info types
All defined types:
 
File /tmp/ccRLPPDo.s:
typedef void;
 
File helloworld.c:
typedef double;
typedef int;
typedef long int;
typedef long long int;
typedef long long unsigned int;
typedef long unsigned int;
typedef signed char;
 
File /opt/cross/avr/avr/include/stdint.h:
typedef unsigned int uint16_t;
typedef long unsigned int uint32_t;
typedef unsigned char uint8_t;
 
File helloworld.c:
typedef unsigned char;
typedef unsigned int;
 
Non-debugging symbols:
0x00000000  __heap_end
0x00000000  __tmp_reg__
0x00000001  __zero_reg__
0x0000003d  __SP_L__
0x0000003e  __SP_H__
0x0000003f  __SREG__
0x00000074  __data_load_end
0x00000074  __data_load_start
0x0000025f  __stack
 
(gdb) info line
Line 164 of "/opt/cross/avr/avr/include/util/delay.h" starts at address 0x32 <main+2> and ends at 0x3e <main+14>.
 
Stack commands:
(gdb) backtrace 
#0  0x00000048 in _delay_ms (__ms=10) at /opt/cross/avr/avr/include/util/delay.h:164
#1  main () at helloworld.c:21
 
Navigate stack using commands up and down.
(gdb) up
#1  main () at helloworld.c:21
21                   _delay_ms(10); // Call delay for 300 milisec
 
Inspect variable:
(gdb) inspect delay
$1 = 1000