UP | HOME
AVR microcontroller resources
_____

AVR microcontroller resources

IN PROGRESS

Detailing open hardware and free software for the use and programming of Atmel's AVR family of microcontrollers and boards, including the ATmega8/128/168 microcontrollers, AVR-HID, Byron , various Atmel USB micros, Arduino/Freeduino//alikes and scrying platforms.

Table of Contents

1 overview

  • range of possibilities.
  • questions of diversity

2 Hardware/software solutions

2.2 Arduino

2.4 xxxxx-AVR-HID

2.4.1 surface mount (SMD) version

2.4.2 through hole version

2.5 Byron [the board]

../images/byron1.jpg

Byron is a flexible, low budget open hardware and free software platform for fast, multiple sensor input and control over USB. Byron differs from other solutions in terms of speed, simplicity and low cost.

Using a pre-flashed bootloader, Byron is able to assume new identities, for example functioning one moment as a microcontroller programmer to flash new devices, the next as a straightforward keyboard device. Byron is based on Objective Development's V-USB software.

Please visit: byron for more details.

3 generic programming and development environment

3.1 In C/C++

3.1.1 Example project code

  • Arduino vs straight C
    • Arduino code
    • Equivalent C code

3.1.2 Developing using avr-gcc and commandline

3.1.3 toolchain

  • avr-gcc and avr-objcopy

    Compile:

    avr-gcc -g -Os -mmcu=atmega8 -c test.c 
    

    Link:

    avr-gcc -g -mmcu=atmega8 -o test.elf test.o
    

    Generate .hex (ihex format):

    avr-objcopy -j .text -j .data -O ihex test.elf test.hex
    
  • Makefile

    To automate compiling and linking of code files. The Makefile can also be used to automate program upload, and disassembly.

  • Other tools

3.1.4 Makefile example/s

  • 1]

Not sure where this came from but it's a generic Makefile - only need to change microcontroller and programmer if different from specified (here for the Atmega8). It will compile,link all files in the directory and generate the necessary .hex file.

make flash

will also upload the code.

NAME := main
HEX := $(NAME).hex
OUT := $(NAME).out
MAP := $(NAME).map
SOURCES := $(wildcard *.c)
HEADERS := $(wildcard *.h)
OBJECTS := $(patsubst %.c,%.o,$(SOURCES))

MCU := atmega8
MCU_AVRDUDE := m8

CC := avr-gcc
OBJCOPY := avr-objcopy
SIZE := avr-size -A
DOXYGEN := doxygen

CFLAGS := -Wall -pedantic -mmcu=$(MCU) -std=c99 -g -Os

all: $(HEX)

clean:
        rm -f $(HEX) $(OUT) $(MAP) $(OBJECTS)
        rm -rf doc/html

flash: $(HEX)
        avrdude -y -c usbasp -p $(MCU_AVRDUDE) -U flash:w:$(HEX)

$(HEX): $(OUT)
        $(OBJCOPY) -R .eeprom -O ihex $< $@

$(OUT): $(OBJECTS)
        $(CC) $(CFLAGS) -o $@ -Wl,-Map,$(MAP) $^
        @echo
        @$(SIZE) $@
        @echo

%.o: %.c $(HEADERS)
        $(CC) $(CFLAGS) -c -o $@ $<

%.pp: %.c
        $(CC) $(CFLAGS) -E -o $@ $<

%.ppo: %.c
        $(CC) $(CFLAGS) -E $<

doc: $(HEADERS) $(SOURCES) Doxyfile
        $(DOXYGEN) Doxyfile

.PHONY: all clean flash doc
  • 2] A more advanced Makefile with more options and possibility to generate a disassembly of the C code:

See: http://electrons.psychogenic.com/articles/Makefile.tpl

and use:

make disasm 

To show assembly code.

3.1.5 using GNU/Emacs as an IDE

M-x compile

executes current/local Makefile

3.1.6 Other

  • Use of progmem

    To place a static variable (eg. string, set of values) in flash memory, to save SRAM. Within a function definition:

    static prog_uchar gps0[] PROGMEM ={0x10,0x7A,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x03};
    

    read with:

    pgm_read_byte(gps0+j);
    

    in this case.

3.2 In assembly [also notes relevant to C code]

3.2.1 compile and linking of assembly to elf

avr-gcc -Os -mmcu=atmega8 -Wa,-gstabs -I/usr/lib/avr/include/avr/ -o test.elf test.S

3.2.2 elf to hex:

avr-objcopy -j .text -j .data -O ihex test.elf test.hex

3.2.3 disassembly (use this to get linked full assembly!):

avr-objdump -S test.elf

(only if we compile with -g // debugging // and not -Os (for size optimisation)??)

avr-gcc -g -mmcu=atmega8 -I/usr/lib/avr/include/avr/ memtest.c -o memtest.elf

also to note:

avr-gcc -g -mmcu=atmega8 -Wl,-Map,demo.map -o demo.elf demo.o

3.2.4 __exit is an endless loop.

 26c: ff cf           rjmp    .-2             ; 0x26c <__stop_program>

3.2.5 memory management: flash/rom and SRAM sections

http://www.nongnu.org/avr-libc/user-manual/malloc-std.png

[for the 128]

  • The .text Section

    The .text section contains the actual machine instructions which make up your program. Includes:

  • The .initN Sections

    init code

    • The .finiN Sections

      exit code

  • The .data Section

    This section contains static data which was defined in your code.

  • The .bss Section

    Uninitialized global or static variables end up in the .bss section. Includes:

    • The .noinit Section
  • The .eeprom Section
  • avr-size

    The avr-size program (part of binutils), coming from a Unix background, doesn't account for the .data initialization space added to the .text section, so in order to know how much flash the final program will consume, one needs to add the values for both, .text and .data (but not .bss), while the amount of pre-allocated SRAM is the sum of .data and .bss.

  • malloc?

    The variables __malloc_heap_start and __malloc_heap_end can be used to restrict the malloc() function to a certain memory region. These variables are statically initialized to point to __heap_start and __heap_end, respectively, where __heap_start is filled in by the linker to point just beyond .bss, and __heap_end is set to 0 which makes malloc() assume the heap is below the stack.

  • what is the heap?

    The standard RAM layout is to place .data variables first, from the beginning of the internal RAM, followed by .bss. The stack is started from the top of internal RAM, growing downwards. The so-called "heap" available for the dynamic memory allocator will be placed beyond the end of .bss.

  • note from scrying makefile:

    EXTERNAL_RAM = -Wl,-Tdata=0x801100,–defsym=__heap_end=0x80ffff

    and we use memory pointer directly from 1100 - how do we avoid writing over variables (in serialtest.c case).

  • test serialtest code in scrying

    in new code - also PORTE is set strangely (for gplog to 0x00 , for main log to 0xff)

    same in noise2.c where we write to 1100+ and don't set PORTE

    possible answer as using:

    avr-size noise2.o
    

    we see:

       text    data     bss     dec     hex filename
       8336       4      10    8350    209e noise2.o
    

    how can we see what is in data and bss (-s switch)?

    avr-objdump -sh -S noise2.o
    

    gives:

    0000 0ad7233c
    

    but in the case of serialtest.o we have 621 bytes of data which is all text messages (for help and so on) which we know doesn't get overwritten???

    only conclusion is that data segment is not moved by Makefile (or possibility that as it is stored in ROM/FLASH????)

  • perhaps because…

    The ld (linker) user manual states that using -Tdata=<x> is equivalent to using –section-start,.data=<x>. However, you have to use –section-start as above because the GCC frontend also sets the -Tdata option for all MCU types where the SRAM doesn't start at 0x800060. Thus, the linker is being faced with two -Tdata options. Starting with binutils 2.16, the linker changed the preference, and picks the "wrong" option in this situation.

    From: http://www.nongnu.org/avr-libc/user-manual/malloc.html

    So, where does sram start on the atmega128?

    At 0x0100 -> 0x10FF so we start at 0x1100

    and we shouldn't relocate anything there! (heap is only for malloc)…

3.2.6 concrete memory explorations (ATmega8)

;; x[0]=1;
;; compiles to:

  68:   81 e0           ldi     r24, 0x01       ; 1
  6a:   80 93 60 00     sts     0x0060, r24

from: http://hubbard.engr.scu.edu/embedded/avr/doc/avr-libc/avr-libc-user-manual/group\_\_demo\_\_project.html

The .data segment (where initialized static variables are stored) starts at location 0x60, which is the first address after the register bank on a 2313 processor.

Also:

Direct Addressing Mode : For example the 128 bytes of SRAM in the atmel at90s2313 is all directly accessible for reading and writing you can simply specify the address you wish to store data at and read data from in the instruction . The ram starts at 0x60 ( look up previous tutorials to see why ) so after the 0x60 you can simply read and write using the LDS and STS instructions by simply sepcifying the address which goes something like this ..

LDS R16,0x60 ;move the value at 0x60 to R16 STS 0x60,R16 ;move the value of R16 to 0x60

from: http://www.roboticsindia.com/

Compile: avr-gcc -g -Os -mmcu=atmega8 -c memtest.c

Linking: avr-gcc -g -mmcu=atmega8 -o memtest.elf memtest.o

Map: avr-gcc -g -mmcu=atmega8 -Wl,-Map,memtest.map -o memtest.elf memtest.o

Here we can see:

.data           0x00800060      0x400 load address 0x00000064
                0x00800060                PROVIDE (__data_start, .)
 *(.data)
 .data          0x00800060        0x0 /usr/lib/gcc/avr/4.3.2/../../../avr/lib/avr4/crtm8.o
 .data          0x00800060      0x400 memtest.o
                0x00800060                x
 .data          0x00800460        0x0 /usr/lib/gcc/avr/4.3.2/avr4/libgcc.a(_exit.o)
 .data          0x00800460        0x0 /usr/lib/gcc/avr/4.3.2/avr4/libgcc.a(_copy_data.o)
 .data          0x00800460        0x0 /usr/lib/gcc/avr/4.3.2/avr4/libgcc.a(_clear_bss.o)
 *(.data*)
 *(.rodata)
 *(.rodata*)
 *(.gnu.linkonce.d*)
                0x00800460                . = ALIGN (0x2)
                0x00800460                _edata = .
                0x00800460                PROVIDE (__data_end, .)

.bss            0x00800460        0x0 load address 0x00000464
                0x00800460                PROVIDE (__bss_start, .)
 *(.bss)
 .bss           0x00800460        0x0 /usr/lib/gcc/avr/4.3.2/../../../avr/lib/avr4/crtm8.o
 .bss           0x00800460        0x0 memtest.o
 .bss           0x00800460        0x0 /usr/lib/gcc/avr/4.3.2/avr4/libgcc.a(_exit.o)
 .bss           0x00800460        0x0 /usr/lib/gcc/avr/4.3.2/avr4/libgcc.a(_copy_data.o)
 .bss           0x00800460        0x0 /usr/lib/gcc/avr/4.3.2/avr4/libgcc.a(_clear_bss.o)

Note data->.bss is 0x0400 = 1024 in decimal = size of array we initialised:

unsigned char x[1024]="1234";

Note also: Because of the Harvard architecture of the AVR devices, you must manually add 0x800000 to the address you pass to the linker as the start of the section. Otherwise, the linker thinks you want to put the .noinit section into the .text section instead of .data/.bss and will complain.

How this map translates into hex format?

Hmm, looking at disassambly using:

avr-objdump -m avr -zxhD memtest.hex
  • Examples
    • memtest.c
      #include <stdlib.h>
      
      unsigned char x[128]="1234";
      
      int main(void){
        /*      unsigned char *x;
            x = malloc(1024);
            *x =255;*/
        return;
      }
      
    • memtest.hex
      :1000000012C02CC02BC02AC029C028C027C026C0BF
      :1000100025C024C023C022C021C020C01FC01EC0D4
      :100020001DC01CC01BC011241FBECFE5D4E0DEBF25
      :10003000CDBF10E0A0E6B0E0E4E6F0E002C005903D
      :100040000D92A03EB107D9F710E0A0EEB0E001C0DC
      :100050001D92A03EB107E1F702D002C0D1CF0895B2
      :04006000F894FFCF42
      :1000640031323334000000000000000000000000C2
      :10007400000000000000000000000000000000007C
      :10008400000000000000000000000000000000006C
      :10009400000000000000000000000000000000005C
      :1000A400000000000000000000000000000000004C
      :1000B400000000000000000000000000000000003C
      :1000C400000000000000000000000000000000002C
      :1000D400000000000000000000000000000000001C
      :00000001FF
      

      See: http://www.scienceprog.com/shelling-the-intel-8-bit-hex-file-format/

      10 = byte count 0064 (for example) = address followed by record type (eg. 00) then data and finally checksum (last byte)

      notes: 0x01FF is closing record, from 0064(?) we have the 1,2,3,4 in ASCII (disassembled to instructions below) followed by the zeroed memory

      why is data starting at 0064 and not 0060?

    • memtest.map

      snipped!

       .text          0x0000005c        0x2 /usr/lib/gcc/avr/4.3.2/../../../avr/lib/avr4/crtm8.o
                      0x0000005c                __vector_1
                      0x0000005c                __vector_12
                      0x0000005c                __bad_interrupt
                      0x0000005c                __vector_6
                      0x0000005c                __vector_3
                      0x0000005c                __vector_11
                      0x0000005c                __vector_13
                      0x0000005c                __vector_17
                      0x0000005c                __vector_7
                      0x0000005c                __vector_5
                      0x0000005c                __vector_4
                      0x0000005c                __vector_9
                      0x0000005c                __vector_2
                      0x0000005c                __vector_15
                      0x0000005c                __vector_8
                      0x0000005c                __vector_14
                      0x0000005c                __vector_10
                      0x0000005c                __vector_16
                      0x0000005c                __vector_18
       .text          0x0000005e        0x2 memtest.o
                      0x0000005e                main
       .text          0x00000060        0x0 /usr/lib/gcc/avr/4.3.2/avr4/libgcc.a(_exit.o)
       .text          0x00000060        0x0 /usr/lib/gcc/avr/4.3.2/avr4/libgcc.a(_copy_data.o)
       .text          0x00000060        0x0 /usr/lib/gcc/avr/4.3.2/avr4/libgcc.a(_clear_bss.o)
                      0x00000060                . = ALIGN (0x2)
       *(.text.*)
       .text.libgcc   0x00000060        0x0 /usr/lib/gcc/avr/4.3.2/avr4/libgcc.a(_exit.o)
       .text.libgcc   0x00000060        0x0 /usr/lib/gcc/avr/4.3.2/avr4/libgcc.a(_copy_data.o)
       .text.libgcc   0x00000060        0x0 /usr/lib/gcc/avr/4.3.2/avr4/libgcc.a(_clear_bss.o)
                      0x00000060                . = ALIGN (0x2)
       *(.fini9)
       .fini9         0x00000060        0x0 /usr/lib/gcc/avr/4.3.2/avr4/libgcc.a(_exit.o)
                      0x00000060                exit
                      0x00000060                _exit
       *(.fini9)
       *(.fini8)
       *(.fini8)
       *(.fini7)
       *(.fini7)
       *(.fini6)
       *(.fini6)
       *(.fini5)
       *(.fini5)
       *(.fini4)
       *(.fini4)
       *(.fini3)
       *(.fini3)
       *(.fini2)
       *(.fini2)
       *(.fini1)
       *(.fini1)
       *(.fini0)
       .fini0         0x00000060        0x4 /usr/lib/gcc/avr/4.3.2/avr4/libgcc.a(_exit.o)
       *(.fini0)
                      0x00000064                _etext = .
      
      .data           0x00800060       0x80 load address 0x00000064
                      0x00800060                PROVIDE (__data_start, .)
       *(.data)
       .data          0x00800060        0x0 /usr/lib/gcc/avr/4.3.2/../../../avr/lib/avr4/crtm8.o
       .data          0x00800060       0x80 memtest.o
                      0x00800060                x
       .data          0x008000e0        0x0 /usr/lib/gcc/avr/4.3.2/avr4/libgcc.a(_exit.o)
       .data          0x008000e0        0x0 /usr/lib/gcc/avr/4.3.2/avr4/libgcc.a(_copy_data.o)
       .data          0x008000e0        0x0 /usr/lib/gcc/avr/4.3.2/avr4/libgcc.a(_clear_bss.o)
       *(.data*)
       *(.rodata)
       *(.rodata*)
       *(.gnu.linkonce.d*)
                      0x008000e0                . = ALIGN (0x2)
                      0x008000e0                _edata = .
                      0x008000e0                PROVIDE (__data_end, .)
      
      .bss            0x008000e0        0x0 load address 0x000000e4
                      0x008000e0                PROVIDE (__bss_start, .)
       *(.bss)
       .bss           0x008000e0        0x0 /usr/lib/gcc/avr/4.3.2/../../../avr/lib/avr4/crtm8.o
       .bss           0x008000e0        0x0 memtest.o
       .bss           0x008000e0        0x0 /usr/lib/gcc/avr/4.3.2/avr4/libgcc.a(_exit.o)
       .bss           0x008000e0        0x0 /usr/lib/gcc/avr/4.3.2/avr4/libgcc.a(_copy_data.o)
       .bss           0x008000e0        0x0 /usr/lib/gcc/avr/4.3.2/avr4/libgcc.a(_clear_bss.o)
       *(.bss*)
       *(COMMON)
                      0x008000e0                PROVIDE (__bss_end, .)
                      0x00000064                __data_load_start = LOADADDR (.data)
                      0x000000e4                __data_load_end = (__data_load_start + SIZEOF (.data))
      
    • disassembly from hex using avr-objdump(skipping 00s)
       avr-objdump -m avr -sxhD memtest.hex > memtest.disasm
      
      memtest.hex:     file format ihex
      memtest.hex
      architecture: UNKNOWN!, flags 0x00000000:
      
      start address 0x00000000
      
      Sections:
      Idx Name          Size      VMA       LMA       File off  Algn
        0 .sec1         000000e4  00000000  00000000  00000000  2**0
                        CONTENTS, ALLOC, LOAD
      SYMBOL TABLE:
      no symbols
      
      
      Contents of section .sec1:
       0000 12c02cc0 2bc02ac0 29c028c0 27c026c0  ..,.+.*.).(.'.&.
       0010 25c024c0 23c022c0 21c020c0 1fc01ec0  %.$.#.".!. .....
       0020 1dc01cc0 1bc01124 1fbecfe5 d4e0debf  .......$........
       0030 cdbf10e0 a0e6b0e0 e4e6f0e0 02c00590  ................
       0040 0d92a03e b107d9f7 10e0a0ee b0e001c0  ...>............
       0050 1d92a03e b107e1f7 02d002c0 d1cf0895  ...>............
       0060 f894ffcf 31323334 00000000 00000000  ....1234........
       0070 00000000 00000000 00000000 00000000  ................
       0080 00000000 00000000 00000000 00000000  ................
       0090 00000000 00000000 00000000 00000000  ................
       00a0 00000000 00000000 00000000 00000000  ................
       00b0 00000000 00000000 00000000 00000000  ................
       00c0 00000000 00000000 00000000 00000000  ................
       00d0 00000000 00000000 00000000 00000000  ................
       00e0 00000000                             ....            
      Disassembly of section .sec1:
      
      00000000 <.sec1>:
         0:   12 c0           rjmp    .+36            ;  0x26
         2:   2c c0           rjmp    .+88            ;  0x5c
         4:   2b c0           rjmp    .+86            ;  0x5c
         6:   2a c0           rjmp    .+84            ;  0x5c
         8:   29 c0           rjmp    .+82            ;  0x5c
         a:   28 c0           rjmp    .+80            ;  0x5c
         c:   27 c0           rjmp    .+78            ;  0x5c
         e:   26 c0           rjmp    .+76            ;  0x5c
        10:   25 c0           rjmp    .+74            ;  0x5c
        12:   24 c0           rjmp    .+72            ;  0x5c
        14:   23 c0           rjmp    .+70            ;  0x5c
        16:   22 c0           rjmp    .+68            ;  0x5c
        18:   21 c0           rjmp    .+66            ;  0x5c
        1a:   20 c0           rjmp    .+64            ;  0x5c
        1c:   1f c0           rjmp    .+62            ;  0x5c
        1e:   1e c0           rjmp    .+60            ;  0x5c
        20:   1d c0           rjmp    .+58            ;  0x5c
        22:   1c c0           rjmp    .+56            ;  0x5c
        24:   1b c0           rjmp    .+54            ;  0x5c
        26:   11 24           eor     r1, r1
        28:   1f be           out     0x3f, r1        ; 63
        2a:   cf e5           ldi     r28, 0x5F       ; 95
        2c:   d4 e0           ldi     r29, 0x04       ; 4
        2e:   de bf           out     0x3e, r29       ; 62
        30:   cd bf           out     0x3d, r28       ; 61
        32:   10 e0           ldi     r17, 0x00       ; 0
        34:   a0 e6           ldi     r26, 0x60       ; 96
        36:   b0 e0           ldi     r27, 0x00       ; 0
        38:   e4 e6           ldi     r30, 0x64       ; 100
        3a:   f0 e0           ldi     r31, 0x00       ; 0
        3c:   02 c0           rjmp    .+4             ;  0x42
        3e:   05 90           lpm     r0, Z+
        40:   0d 92           st      X+, r0
        42:   a0 3e           cpi     r26, 0xE0       ; 224
        44:   b1 07           cpc     r27, r17
        46:   d9 f7           brne    .-10            ;  0x3e
        48:   10 e0           ldi     r17, 0x00       ; 0
        4a:   a0 ee           ldi     r26, 0xE0       ; 224
        4c:   b0 e0           ldi     r27, 0x00       ; 0
        4e:   01 c0           rjmp    .+2             ;  0x52
        50:   1d 92           st      X+, r1
        52:   a0 3e           cpi     r26, 0xE0       ; 224
        54:   b1 07           cpc     r27, r17
        56:   e1 f7           brne    .-8             ;  0x50
        58:   02 d0           rcall   .+4             ;  0x5e
        5a:   02 c0           rjmp    .+4             ;  0x60
        5c:   d1 cf           rjmp    .-94            ;  0x0
        5e:   08 95           ret
        60:   f8 94           cli
        62:   ff cf           rjmp    .-2             ;  0x62
        64:   31 32           cpi     r19, 0x21       ; 33
        66:   33 34           cpi     r19, 0x43       ; 67
              ...
      
    • assembly from elf using:
      avr-objdump -h -SD memtest.elf
      

      snipped after data section:

      memtest.elf:     file format elf32-avr
      
      Sections:
      Idx Name          Size      VMA       LMA       File off  Algn
        0 .text         00000064  00000000  00000000  00000074  2**1
                        CONTENTS, ALLOC, LOAD, READONLY, CODE
        1 .data         00000080  00800060  00000064  000000d8  2**0
                        CONTENTS, ALLOC, LOAD, DATA
        2 .stab         00000858  00000000  00000000  00000158  2**2
                        CONTENTS, READONLY, DEBUGGING
        3 .stabstr      0000044e  00000000  00000000  000009b0  2**0
                        CONTENTS, READONLY, DEBUGGING
      Disassembly of section .text:
      
      00000000 <__vectors>:
         0:   12 c0           rjmp    .+36            ; 0x26 <__ctors_end>
         2:   2c c0           rjmp    .+88            ; 0x5c <__bad_interrupt>
         4:   2b c0           rjmp    .+86            ; 0x5c <__bad_interrupt>
         6:   2a c0           rjmp    .+84            ; 0x5c <__bad_interrupt>
         8:   29 c0           rjmp    .+82            ; 0x5c <__bad_interrupt>
         a:   28 c0           rjmp    .+80            ; 0x5c <__bad_interrupt>
         c:   27 c0           rjmp    .+78            ; 0x5c <__bad_interrupt>
         e:   26 c0           rjmp    .+76            ; 0x5c <__bad_interrupt>
        10:   25 c0           rjmp    .+74            ; 0x5c <__bad_interrupt>
        12:   24 c0           rjmp    .+72            ; 0x5c <__bad_interrupt>
        14:   23 c0           rjmp    .+70            ; 0x5c <__bad_interrupt>
        16:   22 c0           rjmp    .+68            ; 0x5c <__bad_interrupt>
        18:   21 c0           rjmp    .+66            ; 0x5c <__bad_interrupt>
        1a:   20 c0           rjmp    .+64            ; 0x5c <__bad_interrupt>
        1c:   1f c0           rjmp    .+62            ; 0x5c <__bad_interrupt>
        1e:   1e c0           rjmp    .+60            ; 0x5c <__bad_interrupt>
        20:   1d c0           rjmp    .+58            ; 0x5c <__bad_interrupt>
        22:   1c c0           rjmp    .+56            ; 0x5c <__bad_interrupt>
        24:   1b c0           rjmp    .+54            ; 0x5c <__bad_interrupt>
      
      00000026 <__ctors_end>:
        26:   11 24           eor     r1, r1
        28:   1f be           out     0x3f, r1        ; 63
        2a:   cf e5           ldi     r28, 0x5F       ; 95
        2c:   d4 e0           ldi     r29, 0x04       ; 4
        2e:   de bf           out     0x3e, r29       ; 62
        30:   cd bf           out     0x3d, r28       ; 61
      
      00000032 <__do_copy_data>:
        32:   10 e0           ldi     r17, 0x00       ; 0
        34:   a0 e6           ldi     r26, 0x60       ; 96
        36:   b0 e0           ldi     r27, 0x00       ; 0
        38:   e4 e6           ldi     r30, 0x64       ; 100
        3a:   f0 e0           ldi     r31, 0x00       ; 0
        3c:   02 c0           rjmp    .+4             ; 0x42 <.do_copy_data_start>
      
      0000003e <.do_copy_data_loop>:
        3e:   05 90           lpm     r0, Z+
        40:   0d 92           st      X+, r0
      
      00000042 <.do_copy_data_start>:
        42:   a0 3e           cpi     r26, 0xE0       ; 224
        44:   b1 07           cpc     r27, r17
        46:   d9 f7           brne    .-10            ; 0x3e <__SP_H__>
      
      00000048 <__do_clear_bss>:
        48:   10 e0           ldi     r17, 0x00       ; 0
        4a:   a0 ee           ldi     r26, 0xE0       ; 224
        4c:   b0 e0           ldi     r27, 0x00       ; 0
        4e:   01 c0           rjmp    .+2             ; 0x52 <.do_clear_bss_start>
      
      00000050 <.do_clear_bss_loop>:
        50:   1d 92           st      X+, r1
      
      00000052 <.do_clear_bss_start>:
        52:   a0 3e           cpi     r26, 0xE0       ; 224
        54:   b1 07           cpc     r27, r17
        56:   e1 f7           brne    .-8             ; 0x50 <.do_clear_bss_loop>
        58:   02 d0           rcall   .+4             ; 0x5e <main>
        5a:   02 c0           rjmp    .+4             ; 0x60 <_exit>
      
      0000005c <__bad_interrupt>:
        5c:   d1 cf           rjmp    .-94            ; 0x0 <__heap_end>
      
      0000005e <main>:
      int main(void){
        /*      unsigned char *x;
            x = malloc(1024);
            *x =255;*/
        return;
      }
        5e:   08 95           ret
      
      00000060 <_exit>:
        60:   f8 94           cli
      
      00000062 <__stop_program>:
        62:   ff cf           rjmp    .-2             ; 0x62 <__stop_program>
      Disassembly of section .data:
      
      00800060 <__data_start>:
        800060:       31 32           cpi     r19, 0x21       ; 33
        800062:       33 34           cpi     r19, 0x43       ; 67
              ...
      

3.2.7 Code to show heap and stack pointers

and available memory

http://www.arduino.cc/playground/Code/AvailableMemory

and showing stack and heap pointers

also: http://forum.pololu.com/viewtopic.php?f=10&t=989#p4218

  • using this code:
    #define F_CPU                    12000000
    #include <avr/io.h>                     
    #include <avr/interrupt.h>
    #include <stdio.h>
    #include <avr/delay.h>
    #include <stdarg.h>
    #include <stdlib.h> 
    #include <stdint.h>
    
    #define UART_BAUD_RATE 9600
    #define UART_BAUD_CALC(UART_BAUD_RATE,F_CPU) ((F_CPU)/((UART_BAUD_RATE)*16l)-1)
    
    uint8_t * heapptr, * stackptr;
    
    void init_uart(void)
    {
      // set baud rate
      UBRRH = (uint8_t)(UART_BAUD_CALC(UART_BAUD_RATE,F_CPU)>>8);
      UBRRL = (uint8_t)UART_BAUD_CALC(UART_BAUD_RATE,F_CPU);
    
      // Enable receiver and transmitter; enable RX interrupt
      UCSRB = (1<<RXEN) | (1<<TXEN);
    
      //asynchronous 8N1
      UCSRC = (1<<URSEL) | (3<<UCSZ0);
    }
    
    static int uart_putchar(char c, FILE *stream);
    
    static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,_FDEV_SETUP_WRITE);
    
    static int uart_putchar(char c, FILE *stream)
    {
      loop_until_bit_is_set(UCSRA, UDRE);
      UDR = c;
      return 0;
    }
    
    int availableMemory(void) {
      int size = 1024; // Use 2048 with ATmega328
      unsigned char *buf;
    
      while ((buf = (unsigned char *) malloc(--size)) == NULL)
        ;
    
      free(buf);
      return size;
    }
    
    void check_mem(void) {
      stackptr = (uint8_t *)malloc(4);          // use stackptr temporarily
      heapptr = stackptr;                     // save value of heap pointer
      free(stackptr);      // free up the memory again (sets stackptr to 0)
      stackptr =  (uint8_t *)(SP);           // save value of stack pointer
    }
    
    
    int main(void)
    {
      unsigned int xx;
      init_uart();
      stdout = &mystdout;
    
      while(1)
        {
          //      xx=availableMemory();
          check_mem();
          printf("stack %d heap %d\n\r", stackptr, heapptr);
          //      printf("memory island %d\n\r", xx);
          _delay_us(100);
        }
    }
    
    • note: we don't run check_mem and availableMemory at the same time as availableMemory seems to increase heap size despite the free() call.
    • avr-size
    avr-size memtest2.elf 
       text    data     bss     dec     hex filename
       3768      40      14    3822     eee memtest2.elf
    
    • so data+bss gives 54 bytes. memory on the ATmega8 starts at 0x60 which is 96 in decimal.
    • 96 + 54 = 150
    • running the stack and heap code we see that the heap starts at 152 and the stack (which is working down from end of memory) at 1111
    • 1111-152=959
    • and running the free memory code alone we see that malloc returns maximum of 959 bytes of free memory!

3.3 Other languages

3.3.1 SCHEME

On scrying board, ATmega128 with 512Kb external memory.

http://scrying.svn.sourceforge.net/viewvc/scrying/

3.3.2 Forth

amforth is a forth language implementation for the Atmel AVR family of microcontrollers. http://amforth.sourceforge.net

see also: http://libarynth.org/amforth?s=amforth

3.3.3 Any others?

3.4 alternatives to the Arduino IDE

3.4.1 GNU Emacs, arduino-mode.el and ardmake/arduino-make.sh

Integrating editing code, compiling code and uploading to the Arduino/arduino-a-like.

  • arduino-mode.el
    • setup

      from:

      http://github.com/bookest/arduino-mode/blob/09fd1b81880072937881799f6a1cc3431c85002a/arduino-mode.el

      Get code:

      git clone git://github.com/bookest/arduino-mode.git
      

      Make sure that arduino-mode.el is on the load path and then:

      (require 'arduino-mode)
      
    • what it offers/how to use

      Loaded as soon as we edit a .pde file.

    • integration with ardmake
      • what is ardmake?

      arduino-make.sh or ardmake is "a command-line Arduino make/build environment". From:

      http://arkku.com/misc/arduino\_make.sh

      • basic use

      1] Install to say /usr/local/bin

      2] cd into the project directory with the .pde

      3] arduino_make.sh upload to compile/link/upload the sketch

      • rough and ready GNU Emacs integration

      ../images/ardemacs1.png

      (defun ard_upload()
        (interactive)
      (shell-command "/usr/local/bin/arduino_make.sh upload &" "*arduino*"))
      
      ;; C-c k to exit straight from M-x serial-term
      
      (defun ser_mon()
        (interactive)
        (make-serial-process :port "/dev/ttyUSB0" :speed 9600 :buffer "serial monitor")
        (switch-to-buffer "serial monitor"))
      

4 Code upload/the programmer

4.2 generic hardware

For our choices of programming hardware we make use of an ISP (in system programming) interface which accesses the to-be-programmed chip on the following pins (ATmega8 and 168):

Pin 22 : GND
Pin 19: SCK
Pin 18: MISO
Pin 17: MOSI
Pin 1: RESET 

And for the ATmega128 we use PDI/PDO rather than MISO/MOSI as follows:

Pin 22 : GND
Pin 11: SCK
Pin 3: PDO
Pin 2: PDI
Pin 20: RESET 

4.3 programming the AVR-HID[SMD] or Byron

Both present a standard 10 pin ISP (In System Programming) header. A programmer (see below) is simply attached to the board (in the case of usbasp with a straight 10 pin to 10 pin cable. The left-most of the top right jumpers (vertical) must be closed to allow the board to be programmed!

Pins as follows (with pin 1 as top right of the 10 pins):

1 MOSI
2 +5V
3 LED or n/c
4 GND
5 RESET
6 GND
7 SCK
8 GND
9 MISO
10 GND 

4.4 programming the Arduino/arduino-alike using an external programmer

4.5 programmers

4.5.1 AvrUsb500

http://1010.co.uk/images/avrusb.png

From Guido Socher: http://tuxgraphics.org/electronics/200510/article05101.shtml

5 pin ISP header as detailed above (for Mega8/168)

4.5.2 BSD-Programmer

http://1010.co.uk/images/parprg.jpg

See: http://www.bsdhome.com/avrdude/

Attaches to the parallel port and only works on (mostly desktop) machines.

Connect 1K resistors between the parallel port pins and all wires as follows EXCEPT the GND line of the parallel port (18-25) which is connected with straight wire to the AVR's GND pins.

Pins 18-25 (joined) : GND
Pin 8: SCK (1K)
Pin 10: MISO (1K)
Pin 9: MOSI (1K)
Pin 7: RESET (1K) 

4.5.3 Byron as usbasp programmer:

The Byron in SMD format presents a standard 10 pin ISP (In System Programming) cable for programming all AVR parts (see above). The right-most of the two jumpers (vertical) must be closed to allow programming of low frequency parts (eg. straight from the factory 1MHz) as pictured here. Cable also as pictured:

../images/avrprog_jumper.jpg

Using code from: http://www.fischl.de/usbasp to program the ATmega8 on the AVR-HID board.

A new design (bringing out RESET and adding new jumpers) reflects minor changes needed to the (older) board design:

http://1010.co.uk/images/atmega8\_minimal\_usb-Copper2.pdf

4.6 the software - avrdude

Using avrdude to upload a hex file generated by avr-gcc:

To install:

sudo apt-get install avrdude

To program:

;; attach ISP header/cable to target.

;; apply POWER to target if necessary (from USB header or battery)

avrdude -c avrisp2 -p m8 -P /dev/ttyUSB0 -U flash:w:main.hex

;; to use the avrusb500 programmer (on usb serial port ttyUSB0) to
;; program main.hex on the ATmega8 part

avrdude -p m8 -c bsd -U flash:w:main.hex

;; for the BSD programmer (with port described in /etc/avrdude.conf)

avrdude -p m8 -c usbasp -U flash:w:main.hex

;; for our usbasp programmer

http://www.bsdhome.com/avrdude/

4.6.1 other softwares for programming

4.7 fusebits

Fusebits need to be programmed to make use of external oscillators, brownout detection and other functionalities outlined in the data sheet for the relevant part.

4.7.2 How to set these using avrdude

As part of code upload:

avrdude -c usbasp -p m8 -U lfuse:w:0xFF:m -U hfuse:w:0xDF:m -U flash:w:main.hex

Non-interactively:

avrdude -c usbasp -p m8 -U lfuse:w:0xFF:m -U hfuse:w:0xDF:m

Interactively:

avrdude -p m8 -u -c usbasp -t -v -v

To invoke the interactive avrdude session with the appropriate programmer (and also in verbose mode)

w lf 0 0xff
w hf 0 0xdf

To write ff to the low fuse and df to the high fuse

5 links

Author: root <m@1010.co.uk>

Date: 2010-11-03 12:24:27 GMT

HTML generated by org-mode 6.31trans in emacs 23