Alle Informationen über das myAVR-MK3-256K-Board

Es geht hier um dieses Experimentier-Board: myAVR Board MK3 256K PLUS

Die Seite ist noch im Aufbau ...

Benötigte Programmpakete: siehe übergeordnete Site im Kapitel "Needed software". Für Assembler-Programmierung wird zusätzlich noch das Paket "automake" benötigt.
Benötigte Dokumente: mindestens Atmega2560 Datasheet (doc2549.pdf) und doc0856.pdf (8-bit AVR Instruction Set).

Contents - Inhaltsverzeichnis:

First example in assembler - Erstes Assembler-Beispiel
First steps - Erste Schritte
Simple example in assembler - Einfaches Assembler-Beispiel
Simple c program - Erstes einfaches c-Programm
Known errors - Bekannte Fehler
Bootloader
USB connection - USB-Verbindung
Downloads - Beispiele runterladen
Links

First example in assembler - Erstes Assembler-Beispiel

Als Schnellstart hier ein erstes extrem einfaches Assembler-Programm für den Atmega2560:
For a quick start a first very simple assembler program for Atmega2560:
;; test1.asm
        .equ DDRL=0x10A  ;defining address of DDRL using a hexadezimal number 
        .equ PORTL=0x10B ;defining address of PORTL
main:   ldi r16, 0xFF    ;load immediate register16 with hexadezimal FF
        sts DDRL, r16    ;store to Data Direction Register L, will set all bits on PORTL aus output
        ldi r16, 0x55    ;lets select every second LED
        sts PORTL, r16   ;store to port L, will turn on some LEDs connected to PORTL
L1:     rjmp L1          ;relative jump back to label L1, so it will stay in ths loop for ever (until reset).
Beim laufen lassen dieses Programms sollte jede zweite LED am PORTL leuchten.
Und so wird es übersetzt und installiert:
> avra test1.asm  #Warnung ignorieren
> avrdude -p m2560 -c stk500v2 -P /dev/ttyUSB0 -U flash:w:test1.hex:i
Sollte das nicht auf Anhieb funktionieren, siehe nächstes Kapitel.

First steps - Erste Schritte

(only in german yet - sorry)
Ich hatte einige Probleme das MK3-Board zum korrekten funktionieren zu überreden. Hier werden diese Probleme behandelt, so dass es auch einem Einsteiger möglich sein sollte das Board zum Laufen zu bringen.

Alle Hinweise beziehen sich auf das Arbeiten unter Linux (z.B. Kubuntu-11.10)

Verbindung zum Controller

Der MK3-Programmer muss so eingestellt werden, dass von den 4 LEDs neben dem USB-Stecker die beiden mittleren leuchten. Dies kann erreicht werden indem man den Taster mehrmals drückt. Sollte die LED ganz rechts immer an sein, kann man durch langes Drücken des Tasters diese wieder ausschalten.
Die Verbindung zum Controller testen kann man so:
> avrdude -p m2560 -c stk500v2 -P /dev/ttyUSB0 -v
(Das Zeichen ">" ist das Bereitschaftszeichen und muss nicht mit eingetippt werden)

Sollte "/dev/ttyUSB0" nicht gefunden werden, oder einem andern Gerät zugewiesen sein:
- USB-Kabel ausstecken und mit dem Befehl "ls /dev/tty*" prüfen was schon vorhanden ist.
- USB-Kabel einstecken und wieder "ls /dev/tty*" um zu schauen was neu da ist.
Wenn jetzt neu z.B. "/dev/ttyUSB2" erkannt wird, dann dieses beim Verbindungstest verwenden.
Unter MacOSX könnte es z.B. auch "/dev/tty.serial-0001" sein.

Wenn diese Fehlermeldung kommt:
avrdude: stk500v2_command(): command failed
Dann ist eventuell die externe Stromversorgung nicht eingesteckt.

Wenn alles funktioniert, sollte unter anderem folgendes angezeigt werden:

avrdude: Device signature = 0x1e9801
avrdude: safemode: lfuse reads as F7
avrdude: safemode: hfuse reads as D5
avrdude: safemode: efuse reads as FD

avrdude: safemode: lfuse reads as F7
avrdude: safemode: hfuse reads as D5
avrdude: safemode: efuse reads as FD
avrdude: safemode: Fuses OK

Fusebits richtig einstellen

Mit den Fusebits werden einige Dinge eingestellt, die wichtig sind, dass der Controller richtig läuft. Leider sind diese Fusebits (zumindest beim myAvrStamp256) falsch voreingestellt. Die Fusebits werden beim Verbindungstest wie oben beschrieben angezeigt.
Hier eine Zusammenfassung über die Fusebits beim Atmega2560
Ausführlichere Informationen können im Datenblatt zum Atmega2560 gefunden werden.

Wichtig mit dem myAvrStamp256 auf dem MK3-Board ist, dass die Fusebits so gesetzt sind, dass der Fullswing-Modus des Quarz-Oszillators gesetzt ist. Falls nicht läuft alles sehr instabil. Zum Beispiel geht ein Programm nur gerade nach neuem Programmieren, aber dann bei einem Reset nicht mehr. Oder manchmal gehts, manchmal dann wieder nicht mehr.

Deshalb ist es wichtig dass "lfuse" so gesetzt ist:

avrdude: safemode: lfuse reads as F7
Dies so setzen kann man mit diesem Befehl:
> avrdude -p m2560 -c stk500v2 -P /dev/ttyUSB0 -U lfuse:w:0xF7:m

Hintergrundbeleuchtung vom LCD funktioniert nicht

Beim laufen lassen des beiliegenden Testprogramms hatte das LCD keine Beleuchtung. Der Grund dafür war einfach: das Board wurde mit einem defekten Transistor ausgeliefert. Dieser Transistor ersetzt durch einen BS107 hat das Problem behoben. (Es müsste auch mit andern Typen gehen. Ist bloss ein Schalttransistor der etwa 100mA aushalten muss.)
Einfacher Test:
;; lcdledtest.asm
.equ    PORTA   = 0x02
.equ    DDRA    = 0x01
main:   ldi r16, (1<<5)
        out DDRA, r16
        ldi r16, (1<<5)  ;(1<<5) fuer Licht ein, oder (0<<5) fuer Licht aus
        out PORTA, r16
        rjmp main

mehr als 64KB geht nicht

Dies ist ein Problem in "avrdude" (Version 5.10 und 5.11). Offenbar ist es ein Bug in avrdude selbst oder ein Fehler im MK3-Programmer (oder beides).
Genaueraus dazu auf einer eigenen Seite: avrdude64k-problem.html.

In diesem Paket ist eine provisorische Umgehung dieses Problems enthalten: rolfslcdtreiber.tar.gz


Simple example in assembler - Einfaches Assembler-Beispiel

Dies ist immer noch ein sehr einfaches Assemblerprogramm, aber mit Include-Datei und Interrupt-Tabelle. Wegen der langen Interrupt-Tabelle sieht es komplizierter aus als es ist.
;; beisp1.asm
.include "m2560def.inc"  ; Definitionen fuer den ATmega2560
; Reset and interrupt vectors ; Meaning
begin:  jmp main              ; Power On Reset
        jmp err_vect          ; External Int0 (INT0_vect)
        jmp err_vect          ; External Int1
        jmp err_vect          ; External Int2
        jmp err_vect          ; External Int3
        jmp err_vect          ; External Int4
        jmp err_vect          ; External Int5
        jmp err_vect          ; External Int6
        jmp err_vect          ; External Int7
        jmp err_vect          ; Pin Change Interrupt PCINT0
        jmp err_vect          ; Pin Change Interrupt PCINT1
        jmp err_vect          ; Pin Change Interrupt PCINT2
        jmp err_vect          ; Watchdog Time-out WDT
        jmp err_vect          ; Timer/Counter2 Compare Match A (TIMER2_COMPA_vect)
        jmp err_vect          ; Timer/Counter2 Compare Match B (TIMER2_COMPB_vect)
        jmp err_vect          ; Timer/Counter2 Overflow (TIMER2_OVF_vect)
        jmp err_vect          ; Timer/Counter1 Capture Event (TIMER1_CAPT_vect)
        jmp err_vect          ; Timer/Counter1 Compare Match A (TIMER1_COMPA_vect)
        jmp err_vect          ; Timer/Counter1 Compare Match B (TIMER1_COMPB_vect)
        jmp err_vect          ; Timer/Counter1 Compare Match C (TIMER1_COMPC_vect)
        jmp err_vect          ; Timer/Counter1 Overflow (TIMER1_OVF_vect)
        jmp err_vect          ; Timer/Counter0 Compare Match A (TIMER0_COMPA_vect)
        jmp err_vect          ; Timer/Counter0 Compare Match B (TIMER0_COMPB_vect)
        jmp err_vect          ; Timer/Counter0 Overflow (TIMER0_OVF_vect)
        jmp err_vect          ; SPI Serial Transfer Complete (SPI_STC_vect)
        jmp err_vect          ; USART0 Rx Complete (USART0_RX_vect)
        jmp err_vect          ; USART0 Data Register Empty (USART0_UDRE_vect)
        jmp err_vect          ; USART0 Tx Complete (USART0_TX_vect)
        jmp err_vect          ; Analog Comparator (ANALOG_COMP_vect)
        jmp err_vect          ; ADC Conversion Complete (ADC_vect)
        jmp err_vect          ; EEPROM Ready (EE_READY_vect)
        jmp err_vect          ; Timer/Counter3 Capture Event (TIMER3_CAPT_vect)
        jmp err_vect          ; Timer/Counter3 Compare Match A (TIMER3_COMPA_vect)
        jmp err_vect          ; Timer/Counter3 Compare Match B (TIMER3_COMPB_vect)
        jmp err_vect          ; Timer/Counter3 Compare Match C (TIMER3_COMPC_vect)
        jmp err_vect          ; Timer/Counter3 Overflow (TIMER3_OVF_vect)
        jmp err_vect          ; USART1 Rx Complete (USART1_RX_vect)
        jmp err_vect          ; USART1 Data Register Empty (USART1_UDRE_vect)
        jmp err_vect          ; USART1 Tx Complete (USART1_TX_vect)
        jmp err_vect          ; TWI (I2C) 2-wire Serial Interface (TWI_vect)
        jmp err_vect          ; Store Program Memory Ready (SPM_READY_vect)
        jmp err_vect          ; Timer/Counter4 Capture Event (TIMER4_CAPT_vect)
        jmp err_vect          ; Timer/Counter4 Compare Match A (TIMER4_COMPA_vect)
        jmp err_vect          ; Timer/Counter4 Compare Match B (TIMER4_COMPB_vect)
        jmp err_vect          ; Timer/Counter4 Compare Match C (TIMER4_COMPC_vect)
        jmp err_vect          ; Timer/Counter4 Overflow (TIMER4_OVF_vect)
        jmp err_vect          ; Timer/Counter5 Capture Event (TIMER5_CAPT_vect)
        jmp err_vect          ; Timer/Counter5 Compare Match A (TIMER5_COMPA_vect)
        jmp err_vect          ; Timer/Counter5 Compare Match B (TIMER5_COMPB_vect)
        jmp err_vect          ; Timer/Counter5 Compare Match C (TIMER5_COMPC_vect)
        jmp err_vect          ; Timer/Counter5 Overflow (TIMER5_OVF_vect)
        jmp err_vect          ; USART2 Rx Complete (USART2_RX_vect)
        jmp err_vect          ; USART2 Data Register Empty (USART2_UDRE_vect)
        jmp err_vect          ; USART2 Tx Complete (USART2_TX_vect)
        jmp err_vect          ; USART3 Rx Complete (USART3_RX_vect)
        jmp err_vect          ; USART3 Data Register Empty (USART3_UDRE_vect)
        jmp err_vect          ; USART3 Tx Complete (USART3_TX_vect)

err_vect:         ; do something when unexpected Interrupt occures
        push r16
        ldi r16, 0xAA   ; Zur Fehleranzeige z.B. jede 2. LED leuchten lassen
        sts PORTL, r16  ; oder auskommentieren wenn keine Fehlerbehandlung erwuenscht.
        pop r16
        reti            ; return from interrupt
;       jmp begin       ; or jump to make a reset

main:
        ldi r16, low(RAMEND)
        out SPL, r16          ; Init Stackpointer L
        ldi r16, high(RAMEND)
        out SPH, r16          ; Init Stackpointer H
        ldi r16, 0xFF         ; Lade Register r16 mit hexadezimal FF
        sts DDRL, r16         ; auf DDRL speichern um gesamten PORTL als Ausgabe zu definieren
        ldi r16, 0x07         ; z.B. erste 3 LEDs einschalten
mainloop:
        sts PORTL, r16        ; auf PORTL speichern um LEDs leuchten zu lassen
        clc                   ; clear carry - Uebertrag-Bit loeschen
        rol r16               ; rotate left - nach links rotieren
        brcc L1               ; branch if carry clear - springe wenn Ubertrags-Bit aus ist
        ori r16, 1            ; otherwise: set bit 0 - sonst: setze Bit 0 in r16
L1:     rcall wait
        rjmp mainloop         ; relative jump back to label mainloop, will stay in ths loop for ever (until reset).

wait:                 ; waiting subroutine
        push r24              ; save registers on stack - Register auf dem Stack sichern
        push r25
        push r16
        ldi r16, 10           ; counter for outer loop
w1:     ldi r24, low(-32000)  ; Registerpaar r25:r24 als 16-Bit Register verwenden. Low Byte in r24, High Byte in r25
        ldi r25, high(-32000) ; use registers r25:24 as 16 bit register, low byte r24, high byte r25
w2:     adiw r24, 1           ; r25:r24 um 1 erhoehen - increment register pair
        brne w2               ; branch if not equal, doing loop until r25:r24 reaches zero - Schlaufe widerholen bis Wert auf 0
        dec r16
        brne w1               ; make outer loop 10 times
        pop r16               ; restore registers from stack - Register vom Stack wieder zurueckholen
        pop r25
        pop r24
        ret
(Im Gegensatz zum Atmega8 müssen hier in der Interrupt-Tabelle wirklich "jmp" Befehle und _nicht_ "rjmp" Befehle verwendet werden. Statt "jmp err_vect" direkt ein "reti" einsetzen wäre hier auch falsch.)
Damit wir nicht immer die Kommandos zum Compilieren und Flashen (übertragen auf den Controller) eintippen müssen, verwenden wir ein makefile:
# makefile
A=avra
N=m2560
P=stk500v2
TTY=/dev/ttyUSB0

all: beisp1.hex

beisp1.hex: beisp1.asm
        $A beisp1.asm

install: beisp1.hex
        avrdude -p $N -c $P -P $(TTY) -U flash:w:beisp1.hex:i
clean:
        rm -f *~ *.obj *.cof
Die Einrückungen müssen jeweils ein Tabulator sein. Genaueres über makefiles siehe Kapitel Makefiles auf der übergeordneten Site.
Und so verwenden wir das makefile:
> make
> make install
Wenn jetzt da beim ersten "make" Fehlermeldungen kommen:
Zuerst m2560def.inc kopieren:
> find /usr/ -name "m2560*.inc"      #im System suchen
> cp /usr/share/avra/m2560def.inc .  #vom gefundenen ins aktuelle Verzeichnis kopieren
Wenns jetzt solche Fehler gibt:
m2560def.inc(44) : Error   : Unknown mnemonic/macro: #pragma
Die kopierte Datei m2560def.inc editieren und die entsprechenden Zeilen mit ";" auskommentieren.
Jetzt kommt vielleicht noch diese Fehlermeldung:
m2560def.inc(47) : Error : Unknown device: ATmega2560
Das lässt sich beheben durch anpassen von avra und neu compilieren. Dazu z.B. unter avra-1.3.0/src/device.c in der "struct device device_list[]" folgende Zeile einfügen:
  {  "ATmega2560",     131072,     0x200,     8192,   4096, DF_NO_ESPM},
Wenn jetzt alles klappt, so sollte das Programm nach dem "make install" automatisch starten, und die LEDs am PORTL entsprechend blinken.

Fotsetzung folgt ...


Simple c program - Erstes einfaches c-Programm

Hier die Grundstruktur eines sehr einfachen c-Programms:
// test1.c
#include <avr/io.h>

int main()
{
 DDRL = 0xFF;    //Data Direction Register L auf Hexadezimal FF setzen: Alle Bits am PORTL als Ausgabe
 PORTL= 0xAA;    //Daten auf PortL ausgeben (z.B. jede zweite LED einschalten)

 while(1)  //mainloop will never end - diese Schlaufe wird nie verlassen
  {

  }

 return 0; //wird nie erreicht
}
Und hier das makefile dazu:
# makefile
M=atmega2560
N=m2560
C=avr-gcc -mmcu=$M -Wall -Os -c
L=avr-gcc -mmcu=$M -Wall -Os
TTY=/dev/ttyUSB0
P=stk500v2

all: test1.hex

test1.hex: test1.c
        $L test1.c -o test1.elf
        avr-objcopy -O ihex -R .eeprom test1.elf test1.hex
        avr-objdump -h -S test1.elf > test1.lss

install: test1.hex
        avrdude -p $N -c $P -P $(TTY) -U flash:w:test1.hex:i

clean:
        rm -f *~ *.elf *.lss
Wenn wir das Programm mit "make" übersetzt haben, dann haben wir neben dem test1.hex noch eine neue Datei test1.lss, in der das Assembler-Programm, das der Compiler erzeugt hat, zu finden ist. Man vergleiche mit unseren ersten einfachen Assembler-Programmen.

Fotsetzung folgt ...


Known errors - Bekannte Fehler


Bootloader

Beim Installieren eines Bootloaders ist das 64KB-Problem zu berücksichtigen!
(Siehe weiter oben.)

Der Bootloader von der myAVR-Seite ist mangels Dokumentation unbrauchbar (zumindest unter Linux).

Einen Bootloader selbst zu schreiben sollte aber ziemlich einfach sein:
AVR_Bootloader_in_C

Hier ein erster Ansatz eines eigenen Bootloaders inklusive makefile mit Umgehung des 64KB-Problems:
cbootloader.tar.gz
Erste Tests mit diesem selbst geschriebenen Bootloader waren schon mal erfolgreich.
Zum Beispiel das Testbeispiel "asmbeispiele/flashcheck" funktioniert. (siehe Downloads)

Funktioniert allerdings bisher nur unter Linux. Unter MacOSX würde es eigentlich auch funktionieren, nur kann ich da keine geeignete Baudrate im "hexprog" einstellen. (Die MacOSX-Version von "hexprog" könnte auch unter Windows gehen, habe ich bisher aber noch nicht probiert.)


USB

Der USB-Anschluss auf dem Stamp ist ein USB-nach-seriell-Wandler und mit dem UART3 des Atmega2560 verbunden.
Der USB-Treiber unter Linux (Kubuntu) ist schon installiert. Für MacOSX und Windows muss noch der Treiber von Siliconlabs installiert werden.

Das Ansprechen von UART3 im Atmega2560 funktioniert fast genau gleich wie hier beschrieben: UART-Tutorial bei mikrocontroller.net

Ein entsprechnendes Beispiel für den Atmega2560 hier:

// uart_test.c
#include <avr/io.h>
#include <inttypes.h>
#ifndef bool
#define bool int8_t
#endif

#define F_CPU 16000000UL
#define BAUD 500000UL  // Baudrate

// Berechnungen:
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)  // clever runden
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))    // Reale Baudrate
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD)     // Fehler in Promille, 1000 = kein Fehler.
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
  #error Systematischer Fehler der Baudrate groesser 1% und damit zu hoch! 
#endif

void uart_init()
{
 UBRR3 = UBRR_VAL;
 UCSR3B = (1<<RXEN3) | (1<<TXEN3); // UART3 RX und TX einschalten
 //UCSR3C = (1<<USBS3)|(3<<UCSZ30); // Asynchron 8N2
 UCSR3C = (3<<UCSZ30); // Asynchron 8N1
}

void uart_putc(char c)
{
 while (!(UCSR3A & (1<<UDRE3))) ;// warten bis Senden moeglich
 UDR3 = c;                       // sende Zeichen
}

bool uart_getcheck()
{
 return (UCSR3A & (1<<RXC3)); //true wenn ein Zeichen verfuegbar
}

char uart_getc(void)
{
 while (!(UCSR3A & (1<<RXC3))) ;// warten bis Zeichen verfuegbar
 return UDR3; // Zeichen aus UDR an Aufrufer zurueckgeben
}

void uart_write(const char *s)
{
 char c;
 while((c= *s++)!=0) uart_putc(c);
}

void uart_getzeile(char *zeile,int max)
{
 char c;
 while(1)
  {if(uart_getcheck())
    {
     c = uart_getc(); if(c=='\n' || max<=1) {*zeile=0; return;}
     if(c>=' ') {*zeile++ = c; --max;}
    }
  }
}

int main()
{
 char zeile[80];
 uart_init();
 uart_write("Hallo Welt\n"); //wenn Gegenstelle ein Windows-Programm ist, eventuell "\r\n" machen.
 while(1)
  {
   uart_getzeile(zeile,80);
   uart_write(zeile); uart_write("-ok\n");
  }
 return 0;
}
Auf dem Computer braucht es noch ein Programm, das mit den Daten, die der Microkontroller sendet, etwas anfangen kann, und auch Daten sendet, mit denen das Microkontroller-Programm was anfangen kann.
Ein entsprechendes einfaches Testprogramm: Seriell-Tester
Es gibt auch sogenannte Terminal-Programme die etwa das gleiche machen.

Downloads


Links

Datasheets - Datenblätter

Schaltschemas

Schaltschemas vom MK3-Board und vom Stamp256 sind auf der myAVR-Seite zu finden:
Schaltschema MK3-Board
Schaltschema myAVR Stamp
Es gibt ein paar kleine Fehler in den Schaltschemas:

Own sites - Eigene Internet-Seiten

Other sites - Andere Internet-Seiten


Last update: 6.Nov.2012 / Rolf                                                                                 Validator