PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Mega32 Bootloader



Kampi
28.01.2014, 22:24
Heyho,

ich probiere gerade mich in die Geschichte mit den Bootloadern für Atmel AVR MCUs einzuarbeiten und benutze dieses Tut:

http://www.mikrocontroller.net/articles/AVR_Bootloader_in_C_-_eine_einfache_Anleitung

Ich habe das Programm für den ersten Test kopiert und wollte es auf meinen AVR aufspielen.
Wenn ich die Startadresse im Linker nicht ändere funktioniert das Programm. Wenn ich die Adresse aber bei einer Bootloadergröße von 1024W auf 0x7800 ändere (2*0x3C00) passiert gar nichts :/
Ich habe unter den Projekteigenschaften/Toolchain/Linker/Misc folgendes eingefügt:

-Wl,--section-start=.text=0x7800

Wo habe ich evtl. was übersehen?
Danke für die Hilfe!

Wsk8
29.01.2014, 10:08
Ok, 0x7800 stimmt.

Hast du das BOOTRST-Flag auf 0 gesetzt?
BOOTSZ0/1 richtig gesetzt?

Das sollte reichen bei "Other Linker flags":


-Ttext=0x7800


mfg

Kampi
29.01.2014, 15:46
Hey,

das Bit ist gelöscht (Haken gesetzt) und ich habe in AVR Studio eine Bootloadergröße von 1024W angegeben.
Die Linkerdirektive habe ich ebenfalls eingefügt, aber es funktioniert nicht :/
Fuses sind:

High: 0xDA
Low: 0x24

Wsk8
29.01.2014, 16:05
Sicher das dein Code richtig ist??
Wenn kein anderes Programm im Flash steht, wird der Bootloader so oder so ausgeführt, da der PC einfach bis zu 0x7800 läuft.
Kopieren kannst du das Programm zudem NICHT. Das wurde für einen Mega8 geschrieben, du hast einen Mega32.

mfg

Kampi
29.01.2014, 16:18
Hey,

also mein Code sieht atm so aus:



#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/boot.h>
#include <util/delay.h>
#include "uart.h"

#define BOOT_UART_BAUD_RATE 9600 /* Baudrate */
#define XON 17 /* XON Zeichen */
#define XOFF 19 /* XOFF Zeichen */

int main()
{
unsigned int c=0; /* Empfangenes Zeichen + Statuscode */
unsigned char temp, /* Variable */
flag=1, /* Flag zum steuern der Endlosschleife */
p_mode=0; /* Flag zum steuern des Programmiermodus */
void (*start)( void ) = 0x0000; /* Funktionspointer auf 0x0000 */

/* Interrupt Vektoren verbiegen */

char sregtemp = SREG;
cli();
temp = GICR;
GICR = temp | (1<<IVCE);
GICR = temp | (1<<IVSEL);
SREG = sregtemp;

/* Einstellen der Baudrate und aktivieren der Interrupts */
uart_init( UART_BAUD_SELECT(BOOT_UART_BAUD_RATE,F_CPU) );
sei();

uart_puts("Hallo hier ist der Bootloader\n\r");

do
{
c = uart_getc();
if( !(c & UART_NO_DATA) )
{
switch((unsigned char)c)
{
case 'q':
flag=0;
uart_puts("Verlasse den Bootloader!\n\r");
break;
default:
uart_puts("Du hast folgendes Zeichen gesendet: ");
uart_putc((unsigned char)c);
uart_puts("\n\r");
break;
}
}
}
while(flag);

uart_puts("Springe zur Adresse 0x0000!\n\r");

/* vor Rücksprung eventuell benutzte Hardware deaktivieren
und Interrupts global deaktivieren, da kein "echter" Reset erfolgt */

/* Interrupt Vektoren wieder gerade biegen */
cli();
temp = GICR;
GICR = temp | (1<<IVCE);
GICR = temp & ~(1<<IVSEL);

/* Rücksprung zur Adresse 0x0000 */
start();
return 0;
}

Bumbum
29.01.2014, 16:43
Hallo,

ich habe mir deinen Programmcode jetzt nicht angeschaut, aber ich habe einen Hinweis an dem ich mir fast mal die Zähne ausgebissen habe. Ich habe meinen Bootloader-Einstieg damals auch mit dieser Anleitung durchgeführt.

Das Problem ist, es ist mit dem AVR-Studio nicht so einfach das eigentliche Programm und den Bootloader *gleichzeitig* in einen Atmel zu flashen. Das ist ein ganz schönes geklicke und konfigurieren. Mann muss wissen was man tut. Ich tat es als Einsteiger in die Bootload-Technik nicht und war komplett überfordert. Ich habe mir dann als Workaround einen Hex-File-Merger besorgt und diesen via Batch-Datei in eine customized toolbar des AVR-Studio eingebunden. In der Anleitung steht ja auch, dass man die Hex-Dateien zusammenführen soll.

Man kann dann jeweils ein Projekt bearbeiten (Bootloader oder Hauptprogramm) und mit F7 erstellen. Dann noch ein ein kurzer Klick auf den Button zum mergen und dann die zusammengefügte Hex-Datei komplett auf den Atmel flashen.

Vielleicht hilft dir diese Info weiter? Wsk8 hat es richtig beschrieben. Ich habe am Anfang durch das flashen meines Bootloaders immer das Hauptprogramm gelöscht. Den Atmel juckt das nicht. Der Flash steht dann voll mit 0xFF, was ein NOP für den Atmel bedeutet. Er führt also einfach alle Nops aus, bis er im Bootloader landet. Das ganze kann dann ganz schön verwirrend werden...

Viele Grüße
Andreas

Kampi
29.01.2014, 18:17
Hallo,

ich habe mir deinen Programmcode jetzt nicht angeschaut, aber ich habe einen Hinweis an dem ich mir fast mal die Zähne ausgebissen habe. Ich habe meinen Bootloader-Einstieg damals auch mit dieser Anleitung durchgeführt.

Das Problem ist, es ist mit dem AVR-Studio nicht so einfach das eigentliche Programm und den Bootloader *gleichzeitig* in einen Atmel zu flashen. Das ist ein ganz schönes geklicke und konfigurieren. Mann muss wissen was man tut. Ich tat es als Einsteiger in die Bootload-Technik nicht und war komplett überfordert. Ich habe mir dann als Workaround einen Hex-File-Merger besorgt und diesen via Batch-Datei in eine customized toolbar des AVR-Studio eingebunden. In der Anleitung steht ja auch, dass man die Hex-Dateien zusammenführen soll.

Man kann dann jeweils ein Projekt bearbeiten (Bootloader oder Hauptprogramm) und mit F7 erstellen. Dann noch ein ein kurzer Klick auf den Button zum mergen und dann die zusammengefügte Hex-Datei komplett auf den Atmel flashen.

Vielleicht hilft dir diese Info weiter? Wsk8 hat es richtig beschrieben. Ich habe am Anfang durch das flashen meines Bootloaders immer das Hauptprogramm gelöscht. Den Atmel juckt das nicht. Der Flash steht dann voll mit 0xFF, was ein NOP für den Atmel bedeutet. Er führt also einfach alle Nops aus, bis er im Bootloader landet. Das ganze kann dann ganz schön verwirrend werden...

Viele Grüße
Andreas

Hey,

setze ich dafür nicht die Linkerdirektive ein, damit der weiß wo er das Programm hinpacken soll?

Wsk8
29.01.2014, 20:25
Zuerst mal den Flash manuel löschen, dann den Bootloader flashen. Der MUSS dann irgend wann mal aufgerufen werden, sofern alles richtig programmiert und eingestellt wurde.
Wenn dann das Programm geflasht wird, darf der Flash nicht gelöscht werden! Dann sollte auch alles passen.

mfg

Kampi
29.01.2014, 20:49
Hey,

im Moment will ich ja nur den Bootloader drauf packen und der sollte dann eine Meldung ausgeben.

Bumbum
29.01.2014, 20:52
Hallo Kampi,

das mit den Linkerdirektiven sollte so sein, ich bin aber daran verzweifelt.
Der Weg zum Ziel war dann zwei getrennte Projekte, eines für den Bootloader, das andere für das Hauptprogramm. Das hat dann auch noch den Vorteil, dass alles strikt getrennt ist.
Du kannst zum testen die beiden Hex-Files manuell zusammenkopieren. Vom Hauptprogramm die letzte Zeile weg und dann einfach den Bootloader angehängt. Du siehst dann auch gleich in den Hex-Files, ob die Adressen passen. Quasi bist du dann der Linker. Das hilft, um die Vorgänge zu verstehen und mögliche Fehler zu erkennen. Wenn das dann klappt kann ich dir helfen das automatische linken per Shortcut in der Symbolleiste einzurichten.

@Wsk8: Das meine ich mit dem komplizierten vorgehen. Erst Erase Device, dann Bootloader flashen, dann den Hacken bei Auto Erase Device beim Flash Programm weg machen und dann das Hauptprogramm flashen. Und wehe man vergisst einen Schritt beim 34en Test, dann sucht man Fehler wo keine sind. Deshalb mein "automatisiertes" Mergen des Hex-Files. Da muss man dann beim flashen nicht so viel beachten und kann sich aufs programmieren/debuggen konzentrieren.

Viele Grüße
Andreas

Wsk8
29.01.2014, 21:12
@Bumbum
Er hat ja immer noch das Problem, dass der Bootloader noch gar nicht funktioniert ^^

Poste mal das Disasembly und welche Optimierung nutzt du?

mfg

Kampi
29.01.2014, 21:23
Hey,

ich nutze Optimierungsstufe O0 (None).
Meinst du das hier mit Disasembly?:




Bootloader.elf: file format elf32-avr


Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000456 00007800 00007800 00000094 2**1
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000082 00800060 00007c56 000004ea 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000045 008000e2 008000e2 0000056c 2**0
ALLOC
3 .stab 000006cc 00000000 00000000 0000056c 2**2
CONTENTS, READONLY, DEBUGGING
4 .stabstr 00000085 00000000 00000000 00000c38 2**0
CONTENTS, READONLY, DEBUGGING
5 .debug_aranges 00000040 00000000 00000000 00000cbd 2**0
CONTENTS, READONLY, DEBUGGING
6 .debug_pubnames 00000095 00000000 00000000 00000cfd 2**0
CONTENTS, READONLY, DEBUGGING
7 .debug_info 000003b8 00000000 00000000 00000d92 2**0
CONTENTS, READONLY, DEBUGGING
8 .debug_abbrev 00000160 00000000 00000000 0000114a 2**0
CONTENTS, READONLY, DEBUGGING
9 .debug_line 00000435 00000000 00000000 000012aa 2**0
CONTENTS, READONLY, DEBUGGING
10 .debug_frame 000000a0 00000000 00000000 000016e0 2**2
CONTENTS, READONLY, DEBUGGING
11 .debug_str 000001c5 00000000 00000000 00001780 2**0
CONTENTS, READONLY, DEBUGGING
12 .debug_pubtypes 00000049 00000000 00000000 00001945 2**0
CONTENTS, READONLY, DEBUGGING


Disassembly of section .text:


00007800 <__vectors>:
7800: 0c 94 2a 3c jmp 0x7854 ; 0x7854 <__ctors_end>
7804: 0c 94 47 3c jmp 0x788e ; 0x788e <__bad_interrupt>
7808: 0c 94 47 3c jmp 0x788e ; 0x788e <__bad_interrupt>
780c: 0c 94 47 3c jmp 0x788e ; 0x788e <__bad_interrupt>
7810: 0c 94 47 3c jmp 0x788e ; 0x788e <__bad_interrupt>
7814: 0c 94 47 3c jmp 0x788e ; 0x788e <__bad_interrupt>
7818: 0c 94 47 3c jmp 0x788e ; 0x788e <__bad_interrupt>
781c: 0c 94 47 3c jmp 0x788e ; 0x788e <__bad_interrupt>
7820: 0c 94 47 3c jmp 0x788e ; 0x788e <__bad_interrupt>
7824: 0c 94 47 3c jmp 0x788e ; 0x788e <__bad_interrupt>
7828: 0c 94 47 3c jmp 0x788e ; 0x788e <__bad_interrupt>
782c: 0c 94 47 3c jmp 0x788e ; 0x788e <__bad_interrupt>
7830: 0c 94 47 3c jmp 0x788e ; 0x788e <__bad_interrupt>
7834: 0c 94 c9 3c jmp 0x7992 ; 0x7992 <__vector_13>
7838: 0c 94 13 3d jmp 0x7a26 ; 0x7a26 <__vector_14>
783c: 0c 94 47 3c jmp 0x788e ; 0x788e <__bad_interrupt>
7840: 0c 94 47 3c jmp 0x788e ; 0x788e <__bad_interrupt>
7844: 0c 94 47 3c jmp 0x788e ; 0x788e <__bad_interrupt>
7848: 0c 94 47 3c jmp 0x788e ; 0x788e <__bad_interrupt>
784c: 0c 94 47 3c jmp 0x788e ; 0x788e <__bad_interrupt>
7850: 0c 94 47 3c jmp 0x788e ; 0x788e <__bad_interrupt>


00007854 <__ctors_end>:
7854: 11 24 eor r1, r1
7856: 1f be out 0x3f, r1 ; 63
7858: cf e5 ldi r28, 0x5F ; 95
785a: d8 e0 ldi r29, 0x08 ; 8
785c: de bf out 0x3e, r29 ; 62
785e: cd bf out 0x3d, r28 ; 61


00007860 <__do_copy_data>:
7860: 10 e0 ldi r17, 0x00 ; 0
7862: a0 e6 ldi r26, 0x60 ; 96
7864: b0 e0 ldi r27, 0x00 ; 0
7866: e6 e5 ldi r30, 0x56 ; 86
7868: fc e7 ldi r31, 0x7C ; 124
786a: 02 c0 rjmp .+4 ; 0x7870 <__do_copy_data+0x10>
786c: 05 90 lpm r0, Z+
786e: 0d 92 st X+, r0
7870: a2 3e cpi r26, 0xE2 ; 226
7872: b1 07 cpc r27, r17
7874: d9 f7 brne .-10 ; 0x786c <__do_copy_data+0xc>


00007876 <__do_clear_bss>:
7876: 11 e0 ldi r17, 0x01 ; 1
7878: a2 ee ldi r26, 0xE2 ; 226
787a: b0 e0 ldi r27, 0x00 ; 0
787c: 01 c0 rjmp .+2 ; 0x7880 <.do_clear_bss_start>


0000787e <.do_clear_bss_loop>:
787e: 1d 92 st X+, r1


00007880 <.do_clear_bss_start>:
7880: a7 32 cpi r26, 0x27 ; 39
7882: b1 07 cpc r27, r17
7884: e1 f7 brne .-8 ; 0x787e <.do_clear_bss_loop>
7886: 0e 94 49 3c call 0x7892 ; 0x7892 <main>
788a: 0c 94 29 3e jmp 0x7c52 ; 0x7c52 <_exit>


0000788e <__bad_interrupt>:
788e: 0c 94 00 3c jmp 0x7800 ; 0x7800 <__vectors>


00007892 <main>:
#define BOOT_UART_BAUD_RATE 9600 /* Baudrate */
#define XON 17 /* XON Zeichen */
#define XOFF 19 /* XOFF Zeichen */

int main()
{
7892: df 93 push r29
7894: cf 93 push r28
7896: cd b7 in r28, 0x3d ; 61
7898: de b7 in r29, 0x3e ; 62
789a: 28 97 sbiw r28, 0x08 ; 8
789c: 0f b6 in r0, 0x3f ; 63
789e: f8 94 cli
78a0: de bf out 0x3e, r29 ; 62
78a2: 0f be out 0x3f, r0 ; 63
78a4: cd bf out 0x3d, r28 ; 61
unsigned int c=0; /* Empfangenes Zeichen + Statuscode */
78a6: 1b 82 std Y+3, r1 ; 0x03
78a8: 1a 82 std Y+2, r1 ; 0x02
unsigned char temp, /* Variable */
flag=1, /* Flag zum steuern der Endlosschleife */
78aa: 81 e0 ldi r24, 0x01 ; 1
78ac: 89 83 std Y+1, r24 ; 0x01
p_mode=0; /* Flag zum steuern des Programmiermodus */
78ae: 1c 82 std Y+4, r1 ; 0x04
void (*start)( void ) = 0x0000; /* Funktionspointer auf 0x0000 */
78b0: 1e 82 std Y+6, r1 ; 0x06
78b2: 1d 82 std Y+5, r1 ; 0x05

/* Interrupt Vektoren verbiegen */

char sregtemp = SREG;
78b4: 8f e5 ldi r24, 0x5F ; 95
78b6: 90 e0 ldi r25, 0x00 ; 0
78b8: fc 01 movw r30, r24
78ba: 80 81 ld r24, Z
78bc: 8f 83 std Y+7, r24 ; 0x07
cli();
78be: f8 94 cli
temp = GICR;
78c0: 8b e5 ldi r24, 0x5B ; 91
78c2: 90 e0 ldi r25, 0x00 ; 0
78c4: fc 01 movw r30, r24
78c6: 80 81 ld r24, Z
78c8: 88 87 std Y+8, r24 ; 0x08
GICR = temp | (1<<IVCE);
78ca: 8b e5 ldi r24, 0x5B ; 91
78cc: 90 e0 ldi r25, 0x00 ; 0
78ce: 28 85 ldd r18, Y+8 ; 0x08
78d0: 21 60 ori r18, 0x01 ; 1
78d2: fc 01 movw r30, r24
78d4: 20 83 st Z, r18
GICR = temp | (1<<IVSEL);
78d6: 8b e5 ldi r24, 0x5B ; 91
78d8: 90 e0 ldi r25, 0x00 ; 0
78da: 28 85 ldd r18, Y+8 ; 0x08
78dc: 22 60 ori r18, 0x02 ; 2
78de: fc 01 movw r30, r24
78e0: 20 83 st Z, r18
SREG = sregtemp;
78e2: 8f e5 ldi r24, 0x5F ; 95
78e4: 90 e0 ldi r25, 0x00 ; 0
78e6: 2f 81 ldd r18, Y+7 ; 0x07
78e8: fc 01 movw r30, r24
78ea: 20 83 st Z, r18

/* Einstellen der Baudrate und aktivieren der Interrupts */
uart_init( UART_BAUD_SELECT(BOOT_UART_BAUD_RATE,F_CPU) );
78ec: 83 e3 ldi r24, 0x33 ; 51
78ee: 90 e0 ldi r25, 0x00 ; 0
78f0: 0e 94 54 3d call 0x7aa8 ; 0x7aa8 <uart_init>
sei();
78f4: 78 94 sei

uart_puts("Hallo hier ist der Bootloader\n\r");
78f6: 80 e6 ldi r24, 0x60 ; 96
78f8: 90 e0 ldi r25, 0x00 ; 0
78fa: 0e 94 e1 3d call 0x7bc2 ; 0x7bc2 <uart_puts>

do
{
c = uart_getc();
78fe: 0e 94 8d 3d call 0x7b1a ; 0x7b1a <uart_getc>
7902: 9b 83 std Y+3, r25 ; 0x03
7904: 8a 83 std Y+2, r24 ; 0x02
if( !(c & UART_NO_DATA) )
7906: 8a 81 ldd r24, Y+2 ; 0x02
7908: 9b 81 ldd r25, Y+3 ; 0x03
790a: 80 70 andi r24, 0x00 ; 0
790c: 91 70 andi r25, 0x01 ; 1
790e: 00 97 sbiw r24, 0x00 ; 0
7910: c1 f4 brne .+48 ; 0x7942 <main+0xb0>
{
switch((unsigned char)c)
7912: 8a 81 ldd r24, Y+2 ; 0x02
7914: 88 2f mov r24, r24
7916: 90 e0 ldi r25, 0x00 ; 0
7918: 81 37 cpi r24, 0x71 ; 113
791a: 91 05 cpc r25, r1
791c: 31 f4 brne .+12 ; 0x792a <main+0x98>
{
case 'q':
flag=0;
791e: 19 82 std Y+1, r1 ; 0x01
uart_puts("Verlasse den Bootloader!\n\r");
7920: 80 e8 ldi r24, 0x80 ; 128
7922: 90 e0 ldi r25, 0x00 ; 0
7924: 0e 94 e1 3d call 0x7bc2 ; 0x7bc2 <uart_puts>
break;
7928: 0c c0 rjmp .+24 ; 0x7942 <main+0xb0>
default:
uart_puts("Du hast folgendes Zeichen gesendet: ");
792a: 8b e9 ldi r24, 0x9B ; 155
792c: 90 e0 ldi r25, 0x00 ; 0
792e: 0e 94 e1 3d call 0x7bc2 ; 0x7bc2 <uart_puts>
uart_putc((unsigned char)c);
7932: 8a 81 ldd r24, Y+2 ; 0x02
7934: 0e 94 b7 3d call 0x7b6e ; 0x7b6e <uart_putc>
uart_puts("\n\r");
7938: 80 ec ldi r24, 0xC0 ; 192
793a: 90 e0 ldi r25, 0x00 ; 0
793c: 0e 94 e1 3d call 0x7bc2 ; 0x7bc2 <uart_puts>
break;
7940: 00 00 nop
}
}
}
while(flag);
7942: 89 81 ldd r24, Y+1 ; 0x01
7944: 88 23 and r24, r24
7946: d9 f6 brne .-74 ; 0x78fe <main+0x6c>

uart_puts("Springe zur Adresse 0x0000!\n\r");
7948: 83 ec ldi r24, 0xC3 ; 195
794a: 90 e0 ldi r25, 0x00 ; 0
794c: 0e 94 e1 3d call 0x7bc2 ; 0x7bc2 <uart_puts>

/* vor Rücksprung eventuell benutzte Hardware deaktivieren
und Interrupts global deaktivieren, da kein "echter" Reset erfolgt */

/* Interrupt Vektoren wieder gerade biegen */
cli();
7950: f8 94 cli
temp = GICR;
7952: 8b e5 ldi r24, 0x5B ; 91
7954: 90 e0 ldi r25, 0x00 ; 0
7956: fc 01 movw r30, r24
7958: 80 81 ld r24, Z
795a: 88 87 std Y+8, r24 ; 0x08
GICR = temp | (1<<IVCE);
795c: 8b e5 ldi r24, 0x5B ; 91
795e: 90 e0 ldi r25, 0x00 ; 0
7960: 28 85 ldd r18, Y+8 ; 0x08
7962: 21 60 ori r18, 0x01 ; 1
7964: fc 01 movw r30, r24
7966: 20 83 st Z, r18
GICR = temp & ~(1<<IVSEL);
7968: 8b e5 ldi r24, 0x5B ; 91
796a: 90 e0 ldi r25, 0x00 ; 0
796c: 28 85 ldd r18, Y+8 ; 0x08
796e: 2d 7f andi r18, 0xFD ; 253
7970: fc 01 movw r30, r24
7972: 20 83 st Z, r18

/* Rücksprung zur Adresse 0x0000 */
start();
7974: 8d 81 ldd r24, Y+5 ; 0x05
7976: 9e 81 ldd r25, Y+6 ; 0x06
7978: fc 01 movw r30, r24
797a: 09 95 icall
return 0;
797c: 80 e0 ldi r24, 0x00 ; 0
797e: 90 e0 ldi r25, 0x00 ; 0
7980: 28 96 adiw r28, 0x08 ; 8
7982: 0f b6 in r0, 0x3f ; 63
7984: f8 94 cli
7986: de bf out 0x3e, r29 ; 62
7988: 0f be out 0x3f, r0 ; 63
798a: cd bf out 0x3d, r28 ; 61
798c: cf 91 pop r28
798e: df 91 pop r29
7990: 08 95 ret


00007992 <__vector_13>:
ISR (UART0_RECEIVE_INTERRUPT)
/************************************************** ***********************
Function: UART Receive Complete interrupt
Purpose: called when the UART has received a character
************************************************** ************************/
{
7992: 1f 92 push r1
7994: 0f 92 push r0
7996: 0f b6 in r0, 0x3f ; 63
7998: 0f 92 push r0
799a: 11 24 eor r1, r1
799c: 2f 93 push r18
799e: 8f 93 push r24
79a0: 9f 93 push r25
79a2: ef 93 push r30
79a4: ff 93 push r31
79a6: df 93 push r29
79a8: cf 93 push r28
79aa: 00 d0 rcall .+0 ; 0x79ac <__vector_13+0x1a>
79ac: 00 d0 rcall .+0 ; 0x79ae <__vector_13+0x1c>
79ae: cd b7 in r28, 0x3d ; 61
79b0: de b7 in r29, 0x3e ; 62
unsigned char usr;
unsigned char lastRxError;


/* read UART status register and UART data register */
usr = UART0_STATUS;
79b2: 8b e2 ldi r24, 0x2B ; 43
79b4: 90 e0 ldi r25, 0x00 ; 0
79b6: fc 01 movw r30, r24
79b8: 80 81 ld r24, Z
79ba: 8a 83 std Y+2, r24 ; 0x02
data = UART0_DATA;
79bc: 8c e2 ldi r24, 0x2C ; 44
79be: 90 e0 ldi r25, 0x00 ; 0
79c0: fc 01 movw r30, r24
79c2: 80 81 ld r24, Z
79c4: 8b 83 std Y+3, r24 ; 0x03

/* */
#if defined( AT90_UART )
lastRxError = (usr & (_BV(FE)|_BV(DOR)) );
#elif defined( ATMEGA_USART )
lastRxError = (usr & (_BV(FE)|_BV(DOR)) );
79c6: 8a 81 ldd r24, Y+2 ; 0x02
79c8: 88 71 andi r24, 0x18 ; 24
79ca: 89 83 std Y+1, r24 ; 0x01
#elif defined( AT90USB_USART )
lastRxError = (usr & (_BV(FE1)|_BV(DOR1)) );
#endif

/* calculate buffer index */
tmphead = ( UART_RxHead + 1) & UART_RX_BUFFER_MASK;
79cc: 80 91 24 01 lds r24, 0x0124
79d0: 8f 5f subi r24, 0xFF ; 255
79d2: 8f 71 andi r24, 0x1F ; 31
79d4: 8c 83 std Y+4, r24 ; 0x04

if ( tmphead == UART_RxTail ) {
79d6: 80 91 25 01 lds r24, 0x0125
79da: 9c 81 ldd r25, Y+4 ; 0x04
79dc: 98 17 cp r25, r24
79de: 19 f4 brne .+6 ; 0x79e6 <__vector_13+0x54>
/* error: receive buffer overflow */
lastRxError = UART_BUFFER_OVERFLOW >> 8;
79e0: 82 e0 ldi r24, 0x02 ; 2
79e2: 89 83 std Y+1, r24 ; 0x01
79e4: 0b c0 rjmp .+22 ; 0x79fc <__vector_13+0x6a>
}else{
/* store new index */
UART_RxHead = tmphead;
79e6: 8c 81 ldd r24, Y+4 ; 0x04
79e8: 80 93 24 01 sts 0x0124, r24
/* store received data in buffer */
UART_RxBuf[tmphead] = data;
79ec: 8c 81 ldd r24, Y+4 ; 0x04
79ee: 88 2f mov r24, r24
79f0: 90 e0 ldi r25, 0x00 ; 0
79f2: 8e 5f subi r24, 0xFE ; 254
79f4: 9e 4f sbci r25, 0xFE ; 254
79f6: 2b 81 ldd r18, Y+3 ; 0x03
79f8: fc 01 movw r30, r24
79fa: 20 83 st Z, r18
}
UART_LastRxError |= lastRxError;
79fc: 90 91 26 01 lds r25, 0x0126
7a00: 89 81 ldd r24, Y+1 ; 0x01
7a02: 89 2b or r24, r25
7a04: 80 93 26 01 sts 0x0126, r24
}
7a08: 24 96 adiw r28, 0x04 ; 4
7a0a: de bf out 0x3e, r29 ; 62
7a0c: cd bf out 0x3d, r28 ; 61
7a0e: cf 91 pop r28
7a10: df 91 pop r29
7a12: ff 91 pop r31
7a14: ef 91 pop r30
7a16: 9f 91 pop r25
7a18: 8f 91 pop r24
7a1a: 2f 91 pop r18
7a1c: 0f 90 pop r0
7a1e: 0f be out 0x3f, r0 ; 63
7a20: 0f 90 pop r0
7a22: 1f 90 pop r1
7a24: 18 95 reti


00007a26 <__vector_14>:
ISR (UART0_TRANSMIT_INTERRUPT)
/************************************************** ***********************
Function: UART Data Register Empty interrupt
Purpose: called when the UART is ready to transmit the next byte
************************************************** ************************/
{
7a26: 1f 92 push r1
7a28: 0f 92 push r0
7a2a: 0f b6 in r0, 0x3f ; 63
7a2c: 0f 92 push r0
7a2e: 11 24 eor r1, r1
7a30: 2f 93 push r18
7a32: 3f 93 push r19
7a34: 8f 93 push r24
7a36: 9f 93 push r25
7a38: ef 93 push r30
7a3a: ff 93 push r31
7a3c: df 93 push r29
7a3e: cf 93 push r28
7a40: 0f 92 push r0
7a42: cd b7 in r28, 0x3d ; 61
7a44: de b7 in r29, 0x3e ; 62
unsigned char tmptail;



if ( UART_TxHead != UART_TxTail) {
7a46: 90 91 22 01 lds r25, 0x0122
7a4a: 80 91 23 01 lds r24, 0x0123
7a4e: 98 17 cp r25, r24
7a50: a1 f0 breq .+40 ; 0x7a7a <__vector_14+0x54>
/* calculate and store new buffer index */
tmptail = (UART_TxTail + 1) & UART_TX_BUFFER_MASK;
7a52: 80 91 23 01 lds r24, 0x0123
7a56: 8f 5f subi r24, 0xFF ; 255
7a58: 8f 71 andi r24, 0x1F ; 31
7a5a: 89 83 std Y+1, r24 ; 0x01
UART_TxTail = tmptail;
7a5c: 89 81 ldd r24, Y+1 ; 0x01
7a5e: 80 93 23 01 sts 0x0123, r24
/* get one byte from buffer and write it to UART */
UART0_DATA = UART_TxBuf[tmptail]; /* start transmission */
7a62: 8c e2 ldi r24, 0x2C ; 44
7a64: 90 e0 ldi r25, 0x00 ; 0
7a66: 29 81 ldd r18, Y+1 ; 0x01
7a68: 22 2f mov r18, r18
7a6a: 30 e0 ldi r19, 0x00 ; 0
7a6c: 2e 51 subi r18, 0x1E ; 30
7a6e: 3f 4f sbci r19, 0xFF ; 255
7a70: f9 01 movw r30, r18
7a72: 20 81 ld r18, Z
7a74: fc 01 movw r30, r24
7a76: 20 83 st Z, r18
7a78: 09 c0 rjmp .+18 ; 0x7a8c <__vector_14+0x66>
}else{
/* tx buffer empty, disable UDRE interrupt */
UART0_CONTROL &= ~_BV(UART0_UDRIE);
7a7a: 8a e2 ldi r24, 0x2A ; 42
7a7c: 90 e0 ldi r25, 0x00 ; 0
7a7e: 2a e2 ldi r18, 0x2A ; 42
7a80: 30 e0 ldi r19, 0x00 ; 0
7a82: f9 01 movw r30, r18
7a84: 20 81 ld r18, Z
7a86: 2f 7d andi r18, 0xDF ; 223
7a88: fc 01 movw r30, r24
7a8a: 20 83 st Z, r18
}
}
7a8c: 0f 90 pop r0
7a8e: cf 91 pop r28
7a90: df 91 pop r29
7a92: ff 91 pop r31
7a94: ef 91 pop r30
7a96: 9f 91 pop r25
7a98: 8f 91 pop r24
7a9a: 3f 91 pop r19
7a9c: 2f 91 pop r18
7a9e: 0f 90 pop r0
7aa0: 0f be out 0x3f, r0 ; 63
7aa2: 0f 90 pop r0
7aa4: 1f 90 pop r1
7aa6: 18 95 reti


00007aa8 <uart_init>:
Purpose: initialize UART and set baudrate
Input: baudrate using macro UART_BAUD_SELECT()
Returns: none
************************************************** ************************/
void uart_init(unsigned int baudrate)
{
7aa8: df 93 push r29
7aaa: cf 93 push r28
7aac: 00 d0 rcall .+0 ; 0x7aae <uart_init+0x6>
7aae: cd b7 in r28, 0x3d ; 61
7ab0: de b7 in r29, 0x3e ; 62
7ab2: 9a 83 std Y+2, r25 ; 0x02
7ab4: 89 83 std Y+1, r24 ; 0x01
UART_TxHead = 0;
7ab6: 10 92 22 01 sts 0x0122, r1
UART_TxTail = 0;
7aba: 10 92 23 01 sts 0x0123, r1
UART_RxHead = 0;
7abe: 10 92 24 01 sts 0x0124, r1
UART_RxTail = 0;
7ac2: 10 92 25 01 sts 0x0125, r1
/* enable UART receiver and transmmitter and receive complete interrupt */
UART0_CONTROL = _BV(RXCIE)|_BV(RXEN)|_BV(TXEN);


#elif defined (ATMEGA_USART)
/* Set baud rate */
if ( baudrate & 0x8000 )
7ac6: 89 81 ldd r24, Y+1 ; 0x01
7ac8: 9a 81 ldd r25, Y+2 ; 0x02
7aca: 99 23 and r25, r25
7acc: 54 f4 brge .+20 ; 0x7ae2 <uart_init+0x3a>
{
UART0_STATUS = (1<<U2X); //Enable 2x speed
7ace: 8b e2 ldi r24, 0x2B ; 43
7ad0: 90 e0 ldi r25, 0x00 ; 0
7ad2: 22 e0 ldi r18, 0x02 ; 2
7ad4: fc 01 movw r30, r24
7ad6: 20 83 st Z, r18
baudrate &= ~0x8000;
7ad8: 89 81 ldd r24, Y+1 ; 0x01
7ada: 9a 81 ldd r25, Y+2 ; 0x02
7adc: 9f 77 andi r25, 0x7F ; 127
7ade: 9a 83 std Y+2, r25 ; 0x02
7ae0: 89 83 std Y+1, r24 ; 0x01
}
UBRRH = (unsigned char)(baudrate>>8);
7ae2: 80 e4 ldi r24, 0x40 ; 64
7ae4: 90 e0 ldi r25, 0x00 ; 0
7ae6: 29 81 ldd r18, Y+1 ; 0x01
7ae8: 3a 81 ldd r19, Y+2 ; 0x02
7aea: 23 2f mov r18, r19
7aec: 33 27 eor r19, r19
7aee: fc 01 movw r30, r24
7af0: 20 83 st Z, r18
UBRRL = (unsigned char) baudrate;
7af2: 89 e2 ldi r24, 0x29 ; 41
7af4: 90 e0 ldi r25, 0x00 ; 0
7af6: 29 81 ldd r18, Y+1 ; 0x01
7af8: fc 01 movw r30, r24
7afa: 20 83 st Z, r18

/* Enable USART receiver and transmitter and receive complete interrupt */
UART0_CONTROL = _BV(RXCIE)|(1<<RXEN)|(1<<TXEN);
7afc: 8a e2 ldi r24, 0x2A ; 42
7afe: 90 e0 ldi r25, 0x00 ; 0
7b00: 28 e9 ldi r18, 0x98 ; 152
7b02: fc 01 movw r30, r24
7b04: 20 83 st Z, r18

/* Set frame format: asynchronous, 8data, no parity, 1stop bit */
#ifdef URSEL
UCSRC = (1<<URSEL)|(3<<UCSZ0);
7b06: 80 e4 ldi r24, 0x40 ; 64
7b08: 90 e0 ldi r25, 0x00 ; 0
7b0a: 26 e8 ldi r18, 0x86 ; 134
7b0c: fc 01 movw r30, r24
7b0e: 20 83 st Z, r18

/* Set frame format: asynchronous, 8data, no parity, 1stop bit */
UCSR1C = (1<<UCSZ11)|(1<<UCSZ10);
#endif


}/* uart_init */
7b10: 0f 90 pop r0
7b12: 0f 90 pop r0
7b14: cf 91 pop r28
7b16: df 91 pop r29
7b18: 08 95 ret


00007b1a <uart_getc>:
Purpose: return byte from ringbuffer
Returns: lower byte: received byte from ringbuffer
higher byte: last receive error
************************************************** ************************/
unsigned int uart_getc(void)
{
7b1a: df 93 push r29
7b1c: cf 93 push r28
7b1e: 00 d0 rcall .+0 ; 0x7b20 <uart_getc+0x6>
7b20: cd b7 in r28, 0x3d ; 61
7b22: de b7 in r29, 0x3e ; 62
unsigned char tmptail;
unsigned char data;




if ( UART_RxHead == UART_RxTail ) {
7b24: 90 91 24 01 lds r25, 0x0124
7b28: 80 91 25 01 lds r24, 0x0125
7b2c: 98 17 cp r25, r24
7b2e: 19 f4 brne .+6 ; 0x7b36 <uart_getc+0x1c>
return UART_NO_DATA; /* no data available */
7b30: 80 e0 ldi r24, 0x00 ; 0
7b32: 91 e0 ldi r25, 0x01 ; 1
7b34: 17 c0 rjmp .+46 ; 0x7b64 <uart_getc+0x4a>
}

/* calculate /store buffer index */
tmptail = (UART_RxTail + 1) & UART_RX_BUFFER_MASK;
7b36: 80 91 25 01 lds r24, 0x0125
7b3a: 8f 5f subi r24, 0xFF ; 255
7b3c: 8f 71 andi r24, 0x1F ; 31
7b3e: 89 83 std Y+1, r24 ; 0x01
UART_RxTail = tmptail;
7b40: 89 81 ldd r24, Y+1 ; 0x01
7b42: 80 93 25 01 sts 0x0125, r24

/* get data from receive buffer */
data = UART_RxBuf[tmptail];
7b46: 89 81 ldd r24, Y+1 ; 0x01
7b48: 88 2f mov r24, r24
7b4a: 90 e0 ldi r25, 0x00 ; 0
7b4c: 8e 5f subi r24, 0xFE ; 254
7b4e: 9e 4f sbci r25, 0xFE ; 254
7b50: fc 01 movw r30, r24
7b52: 80 81 ld r24, Z
7b54: 8a 83 std Y+2, r24 ; 0x02

data = (UART_LastRxError << 8) + data;
7b56: 80 91 26 01 lds r24, 0x0126
UART_LastRxError = 0;
7b5a: 10 92 26 01 sts 0x0126, r1
return data;
7b5e: 8a 81 ldd r24, Y+2 ; 0x02
7b60: 88 2f mov r24, r24
7b62: 90 e0 ldi r25, 0x00 ; 0


}/* uart_getc */
7b64: 0f 90 pop r0
7b66: 0f 90 pop r0
7b68: cf 91 pop r28
7b6a: df 91 pop r29
7b6c: 08 95 ret


00007b6e <uart_putc>:
Purpose: write byte to ringbuffer for transmitting via UART
Input: byte to be transmitted
Returns: none
************************************************** ************************/
void uart_putc(unsigned char data)
{
7b6e: df 93 push r29
7b70: cf 93 push r28
7b72: 00 d0 rcall .+0 ; 0x7b74 <uart_putc+0x6>
7b74: cd b7 in r28, 0x3d ; 61
7b76: de b7 in r29, 0x3e ; 62
7b78: 8a 83 std Y+2, r24 ; 0x02
unsigned char tmphead;



tmphead = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;
7b7a: 80 91 22 01 lds r24, 0x0122
7b7e: 8f 5f subi r24, 0xFF ; 255
7b80: 8f 71 andi r24, 0x1F ; 31
7b82: 89 83 std Y+1, r24 ; 0x01

while ( tmphead == UART_TxTail ){
7b84: 00 00 nop
7b86: 80 91 23 01 lds r24, 0x0123
7b8a: 99 81 ldd r25, Y+1 ; 0x01
7b8c: 98 17 cp r25, r24
7b8e: d9 f3 breq .-10 ; 0x7b86 <uart_putc+0x18>
;/* wait for free space in buffer */
}

UART_TxBuf[tmphead] = data;
7b90: 89 81 ldd r24, Y+1 ; 0x01
7b92: 88 2f mov r24, r24
7b94: 90 e0 ldi r25, 0x00 ; 0
7b96: 8e 51 subi r24, 0x1E ; 30
7b98: 9f 4f sbci r25, 0xFF ; 255
7b9a: 2a 81 ldd r18, Y+2 ; 0x02
7b9c: fc 01 movw r30, r24
7b9e: 20 83 st Z, r18
UART_TxHead = tmphead;
7ba0: 89 81 ldd r24, Y+1 ; 0x01
7ba2: 80 93 22 01 sts 0x0122, r24


/* enable UDRE interrupt */
UART0_CONTROL |= _BV(UART0_UDRIE);
7ba6: 8a e2 ldi r24, 0x2A ; 42
7ba8: 90 e0 ldi r25, 0x00 ; 0
7baa: 2a e2 ldi r18, 0x2A ; 42
7bac: 30 e0 ldi r19, 0x00 ; 0
7bae: f9 01 movw r30, r18
7bb0: 20 81 ld r18, Z
7bb2: 20 62 ori r18, 0x20 ; 32
7bb4: fc 01 movw r30, r24
7bb6: 20 83 st Z, r18


}/* uart_putc */
7bb8: 0f 90 pop r0
7bba: 0f 90 pop r0
7bbc: cf 91 pop r28
7bbe: df 91 pop r29
7bc0: 08 95 ret


00007bc2 <uart_puts>:
Purpose: transmit string to UART
Input: string to be transmitted
Returns: none
************************************************** ************************/
void uart_puts(const char *s )
{
7bc2: df 93 push r29
7bc4: cf 93 push r28
7bc6: 00 d0 rcall .+0 ; 0x7bc8 <uart_puts+0x6>
7bc8: cd b7 in r28, 0x3d ; 61
7bca: de b7 in r29, 0x3e ; 62
7bcc: 9a 83 std Y+2, r25 ; 0x02
7bce: 89 83 std Y+1, r24 ; 0x01
while (*s)
7bd0: 0c c0 rjmp .+24 ; 0x7bea <uart_puts+0x28>
uart_putc(*s++);
7bd2: 89 81 ldd r24, Y+1 ; 0x01
7bd4: 9a 81 ldd r25, Y+2 ; 0x02
7bd6: fc 01 movw r30, r24
7bd8: 20 81 ld r18, Z
7bda: 89 81 ldd r24, Y+1 ; 0x01
7bdc: 9a 81 ldd r25, Y+2 ; 0x02
7bde: 01 96 adiw r24, 0x01 ; 1
7be0: 9a 83 std Y+2, r25 ; 0x02
7be2: 89 83 std Y+1, r24 ; 0x01
7be4: 82 2f mov r24, r18
7be6: 0e 94 b7 3d call 0x7b6e ; 0x7b6e <uart_putc>
Input: string to be transmitted
Returns: none
************************************************** ************************/
void uart_puts(const char *s )
{
while (*s)
7bea: 89 81 ldd r24, Y+1 ; 0x01
7bec: 9a 81 ldd r25, Y+2 ; 0x02
7bee: fc 01 movw r30, r24
7bf0: 80 81 ld r24, Z
7bf2: 88 23 and r24, r24
7bf4: 71 f7 brne .-36 ; 0x7bd2 <uart_puts+0x10>
uart_putc(*s++);


}/* uart_puts */
7bf6: 0f 90 pop r0
7bf8: 0f 90 pop r0
7bfa: cf 91 pop r28
7bfc: df 91 pop r29
7bfe: 08 95 ret


00007c00 <uart_puts_p>:
Purpose: transmit string from program memory to UART
Input: program memory string to be transmitted
Returns: none
************************************************** ************************/
void uart_puts_p(const char *progmem_s )
{
7c00: 1f 93 push r17
7c02: df 93 push r29
7c04: cf 93 push r28
7c06: 00 d0 rcall .+0 ; 0x7c08 <uart_puts_p+0x8>
7c08: 00 d0 rcall .+0 ; 0x7c0a <uart_puts_p+0xa>
7c0a: 0f 92 push r0
7c0c: cd b7 in r28, 0x3d ; 61
7c0e: de b7 in r29, 0x3e ; 62
7c10: 9d 83 std Y+5, r25 ; 0x05
7c12: 8c 83 std Y+4, r24 ; 0x04
register char c;

while ( (c = pgm_read_byte(progmem_s++)) )
7c14: 03 c0 rjmp .+6 ; 0x7c1c <uart_puts_p+0x1c>
uart_putc(c);
7c16: 81 2f mov r24, r17
7c18: 0e 94 b7 3d call 0x7b6e ; 0x7b6e <uart_putc>
************************************************** ************************/
void uart_puts_p(const char *progmem_s )
{
register char c;

while ( (c = pgm_read_byte(progmem_s++)) )
7c1c: 8c 81 ldd r24, Y+4 ; 0x04
7c1e: 9d 81 ldd r25, Y+5 ; 0x05
7c20: 9a 83 std Y+2, r25 ; 0x02
7c22: 89 83 std Y+1, r24 ; 0x01
7c24: 8c 81 ldd r24, Y+4 ; 0x04
7c26: 9d 81 ldd r25, Y+5 ; 0x05
7c28: 01 96 adiw r24, 0x01 ; 1
7c2a: 9d 83 std Y+5, r25 ; 0x05
7c2c: 8c 83 std Y+4, r24 ; 0x04
7c2e: 89 81 ldd r24, Y+1 ; 0x01
7c30: 9a 81 ldd r25, Y+2 ; 0x02
7c32: fc 01 movw r30, r24
7c34: 14 91 lpm r17, Z+
7c36: 1b 83 std Y+3, r17 ; 0x03
7c38: 8b 81 ldd r24, Y+3 ; 0x03
7c3a: 18 2f mov r17, r24
7c3c: 11 23 and r17, r17
7c3e: 59 f7 brne .-42 ; 0x7c16 <uart_puts_p+0x16>
uart_putc(c);


}/* uart_puts_p */
7c40: 0f 90 pop r0
7c42: 0f 90 pop r0
7c44: 0f 90 pop r0
7c46: 0f 90 pop r0
7c48: 0f 90 pop r0
7c4a: cf 91 pop r28
7c4c: df 91 pop r29
7c4e: 1f 91 pop r17
7c50: 08 95 ret


00007c52 <_exit>:
7c52: f8 94 cli


00007c54 <__stop_program>:
7c54: ff cf rjmp .-2 ; 0x7c54 <__stop_program>

Wsk8
29.01.2014, 21:40
Wie ichs mir dachte. Als erstes stell mal auf -Os um



temp = GICR;78c0: 8b e5 ldi r24, 0x5B ; 91
78c2: 90 e0 ldi r25, 0x00 ; 0
78c4: fc 01 movw r30, r24
78c6: 80 81 ld r24, Z
78c8: 88 87 std Y+8, r24 ; 0x08
GICR = temp | (1<<IVCE);
78ca: 8b e5 ldi r24, 0x5B ; 91
78cc: 90 e0 ldi r25, 0x00 ; 0
78ce: 28 85 ldd r18, Y+8 ; 0x08
78d0: 21 60 ori r18, 0x01 ; 1
78d2: fc 01 movw r30, r24
78d4: 20 83 st Z, r18
GICR = temp | (1<<IVSEL);
78d6: 8b e5 ldi r24, 0x5B ; 91
78d8: 90 e0 ldi r25, 0x00 ; 0
78da: 28 85 ldd r18, Y+8 ; 0x08
78dc: 22 60 ori r18, 0x02 ; 2
78de: fc 01 movw r30, r24
78e0: 20 83 st Z, r18
Benötigt viel zu viele Taktzyklen. Muss kürzer sein (<4)

Als Optimierungsstufen empfehlen sich eig nur -Os oder -O1. Der Rest ist, naja... einfach nicht passend.

mfg

Kampi
29.01.2014, 22:09
Wie ichs mir dachte. Als erstes stell mal auf -Os um



temp = GICR;78c0: 8b e5 ldi r24, 0x5B ; 91
78c2: 90 e0 ldi r25, 0x00 ; 0
78c4: fc 01 movw r30, r24
78c6: 80 81 ld r24, Z
78c8: 88 87 std Y+8, r24 ; 0x08
GICR = temp | (1<<IVCE);
78ca: 8b e5 ldi r24, 0x5B ; 91
78cc: 90 e0 ldi r25, 0x00 ; 0
78ce: 28 85 ldd r18, Y+8 ; 0x08
78d0: 21 60 ori r18, 0x01 ; 1
78d2: fc 01 movw r30, r24
78d4: 20 83 st Z, r18
GICR = temp | (1<<IVSEL);
78d6: 8b e5 ldi r24, 0x5B ; 91
78d8: 90 e0 ldi r25, 0x00 ; 0
78da: 28 85 ldd r18, Y+8 ; 0x08
78dc: 22 60 ori r18, 0x02 ; 2
78de: fc 01 movw r30, r24
78e0: 20 83 st Z, r18
Benötigt viel zu viele Taktzyklen. Muss kürzer sein (<4)

Als Optimierungsstufen empfehlen sich eig nur -Os oder -O1. Der Rest ist, naja... einfach nicht passend.

mfg

Whuu das wars :)
Dank dir vielmals!