AVR Studio 4.18 ATmega 16 AVR Dragon WinAVR-20100110 Verbindung über JTAG Hallo Leute, nach mehreren Wochen verzweifelter Problemsuche auf falschen Pfaden (siehe Beitrag "AVR Dragon und AVR Studio EEPROM Limit?" ) denke ich jetzt einen Bug im AVR Studio gefunden zu haben. Eine Tabelle wird im ROM über PROGMEM angelegt. Wenn ich die so in den Controller laden will, hängt sich AVR Studio mit dem Ladebalken in der Mitte stehen bleibend manchmal auf. Anzeige-Fenster: "Platform has been disconnected, leaving debug mode." Danach läßst sich der Controller nicht mehr connecten. Erst ein AVR Studio Neustart ermöglicht einen neuen Connect. Das Ganze ist offenbar abhänig davon wie groß die Tabelle ist. Wenn man "Dummy"-Zeile anfügt oder Zeilen wegläßt geht es mal gut oder schief. Leider habe ich noch keinen Zusammenhang entdeckt. Hatte vielleicht jemand schon mal ein ähnliches Problem mit ROM-Tabellen. Gruß Danni Hier einige Beispiele (OK/Fehlerhaft): Zur besseren Ansicht ggf.in einen Textdatei kopieren. struct eeprom_block_t { uint8_t *eeprom_address; uint8_t *ram_address; void (*init_function)(uint16_t checksum); uint8_t size; }; static const struct eeprom_block_t eeprom_block_table[] PROGMEM= { {(uint8_t*) &eep_sts_positions, (uint8_t*)&rotary_positions, InitMotorControl, sizeof(rotary_positions)}, {(uint8_t*) &eep_x_pos_10m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_12m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_17m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_20m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_20m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, // {(uint8_t*) &eep_x_pos_20m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, // {(uint8_t*) &eep_x_pos_30m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, // {(uint8_t*) &eep_x_pos_40m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, // {(uint8_t*) &eep_x_pos_40m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, }; Hier einige Beispiele incl. Map-File-Auszug: OK: static const struct eeprom_block_t eeprom_block_table[] PROGMEM= { {(uint8_t*) &eep_sts_positions, (uint8_t*)&rotary_positions, InitMotorControl, sizeof(rotary_positions)}, {(uint8_t*) &eep_x_pos_10m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_12m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_17m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_20m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, // {(uint8_t*) &eep_x_pos_20m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, // {(uint8_t*) &eep_x_pos_20m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, // {(uint8_t*) &eep_x_pos_30m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, // {(uint8_t*) &eep_x_pos_40m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, // {(uint8_t*) &eep_x_pos_40m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, }; Map: .progmem.data 0x00000054 0x23 eeprom_handler.o 35 Byte .progmem.data 0x00000077 0x5b cat_control.o .progmem.data 0x000000d2 0x18 switches.o 0x96 oder 150 Byte { Program: 6828 bytes (41.7% Full) Fehlerhaft: static const struct eeprom_block_t eeprom_block_table[] PROGMEM= { {(uint8_t*) &eep_sts_positions, (uint8_t*)&rotary_positions, InitMotorControl, sizeof(rotary_positions)}, {(uint8_t*) &eep_x_pos_10m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_12m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_17m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_20m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_20m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, // {(uint8_t*) &eep_x_pos_20m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, // {(uint8_t*) &eep_x_pos_30m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, // {(uint8_t*) &eep_x_pos_40m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, // {(uint8_t*) &eep_x_pos_40m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, }; Map: .progmem.data 0x00000054 0x2a eeprom_handler.o 42 Byte .progmem.data 0x0000007e 0x5b cat_control.o .progmem.data 0x000000d9 0x18 switches.o 0x9D oder 157 Byte Program: 6836 bytes (41.7% Full) Fehlerhaft: static const struct eeprom_block_t eeprom_block_table[] PROGMEM= { {(uint8_t*) &eep_sts_positions, (uint8_t*)&rotary_positions, InitMotorControl, sizeof(rotary_positions)}, {(uint8_t*) &eep_x_pos_10m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_12m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_17m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_20m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_20m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_20m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, // {(uint8_t*) &eep_x_pos_30m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, // {(uint8_t*) &eep_x_pos_40m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, // {(uint8_t*) &eep_x_pos_40m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, }; Map: .progmem.data 0x00000054 0x31 eeprom_handler.o 49 Byte .progmem.data 0x00000085 0x5b cat_control.o .progmem.data 0x000000e0 0x18 switches.o 0xA4 oder 164 Byte Program: 6842 bytes (41.8% Full) OK: static const struct eeprom_block_t eeprom_block_table[] PROGMEM= { {(uint8_t*) &eep_sts_positions, (uint8_t*)&rotary_positions, InitMotorControl, sizeof(rotary_positions)}, {(uint8_t*) &eep_x_pos_10m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_12m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_17m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_20m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_20m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_20m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_30m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, // {(uint8_t*) &eep_x_pos_40m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, // {(uint8_t*) &eep_x_pos_40m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, }; Map: .progmem.data 0x00000054 0x38 eeprom_handler.o 56 Byte .progmem.data 0x0000008c 0x5b cat_control.o .progmem.data 0x000000e7 0x18 switches.o Program: 6850 bytes (41.8% Full) OK: static const struct eeprom_block_t eeprom_block_table[] PROGMEM= { {(uint8_t*) &eep_sts_positions, (uint8_t*)&rotary_positions, InitMotorControl, sizeof(rotary_positions)}, {(uint8_t*) &eep_x_pos_10m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_12m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_17m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_20m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_20m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_20m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_30m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, {(uint8_t*) &eep_x_pos_30m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, // {(uint8_t*) &eep_x_pos_40m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, // {(uint8_t*) &eep_x_pos_40m, (uint8_t*)&x_pos_table, NULL, sizeof(x_pos_table)}, }; .progmem.data 0x00000054 0x3f eeprom_handler.o 63 Byte .progmem.data 0x00000093 0x5b cat_control.o .progmem.data 0x000000ee 0x18 switches.o Program: 6856 bytes (41.8% Full)
Danni schrieb: > Das Ganze ist offenbar abhänig davon wie groß die Tabelle ist. Wenn man > "Dummy"-Zeile anfügt oder Zeilen wegläßt geht es mal gut oder schief. > Leider habe ich noch keinen Zusammenhang entdeckt. Das hört sich eher nach fremdgehenden Zeigern an. Übrigends, häng ein Besipiel, das den Fehler aufweist, als compilierbaren(!) Quellcode an. So kanns ein anderer besser nachvollziehen. PS: Wo soll das hin? > eeprom_block_table[] PROGMEM eeprom oder flash (progmem)?
Hi Vielleicht solltest du dich mal über den Unterschied zwischen EEMEM und PROGMEM schlau machen. Das AVR-STudio ist mit Sicherheit bugfreier als dein Programm. MfG Spess
Hallo Floh, Zur Erklärung: eeprom_block_t eeprom_block_table[] ist lediglich eine Tabelle im ROM (PROGMEM) mit einer EEPROM-Adresse, einer RAM-Aresse, einem Function-Pointer und einer Länge (Byte). Die EEPROM-Adresse ergibt sich z.B. aus einem EEPROM-Block: static struct x_pos_tab_t eep_x_pos_20m EEMEM={{{1,2},{3,4},{5,6},{7,8},{9,10},{11,12},{13,14},{15,16},{17,18},{ 19,20},{21,22},{23,24},{25,26},{27,28},{29,30},{31,32},{33,34},{35,36},{ 37,38},{39,40}},0xFF}; Dieser Block kann wahlweise auch nicht mit Dummy-Werten initialisiert sein. Hat keinen Einfluß auf das Fehlerbild. Der Code ist in jeder Konstellation (auch einer Fehlerhaften) der Beispiele oben compilierbar, flashbar und stand-alone lauffähig! Nur beim Debugger-Start bricht AVR Studio ab. >Das hört sich eher nach fremdgehenden Zeigern an. Was heißt das? Wie kann das nur den Debugger beeinflussen? Gruß Danni
Danni schrieb: > Zur besseren Ansicht ggf.in einen Textdatei kopieren. Nein. Du hängst deinen Sourcecode als Dateianhang an deinen nächsten Post. Oder glaubst du irgend jemand hat Lust, sich durch den grauenhaft zusammenkopierten Text durchzuwühlen? mfg.
So jetzt gibt es neue Erkenntnisse: Der Code selbst ist offenbar egal, die Länge aber nicht. Ich habe einfach mal ein paar NOP (#define nop() asm volatile ("nop")) in irgendeine folgende Funktioen gehängt um die Codegröße in kleinen Schritten zu variieren. Ergebnis: 1.Codegröße 0x1D04 (6660) Bytes: Programm läßt sich debuggen. 2.Codegröße 0x1A12 (6674) Bytes + 1 NOP: Programm läßt sich nicht debuggen. 3.Codegröße 0x1A14 (6676) Bytes + 2 NOP: Programm läßt sich nicht debuggen. 4.Codegröße 0x1A16 (6678) Bytes + 3 NOP: Programm läßt sich nicht debuggen. 5.Codegröße 0x1A18 (6680) Bytes + 4 NOP: Programm läßt sich debuggen. Sieht nach einem Aligment-Problem aus. Aber was kann das sein? Vor vielen Jahren hatten wir mal das Problem mit einem Compiler der immer muckte bei Codegrößen die durch 4096 oder 2048 (genau weiß ich es nicht mehr) teilbar waren. Ich werde morgen mal den NOP-Versuch in einem anderen C-File wiederholen, um rauszukriegen, ob es nur von der globalen Größe abhängt nur mit diesem Modul zu tun hat. Ich tippe weiterhin auf ein Debugger-Problem. Gruß, Danni
Sorry, hatte mich in einer Zeile vertippt. Es sollte natürlich 1.Codegröße 0x1A10 (6672) Bytes: Programm läßt sich debuggen. heißen. So sieht die Stelle im Original aus:
1 | .text 0x00000000 0x1a10 |
2 | *(.vectors) |
3 | .vectors 0x00000000 0x54 d:/programme/winavr-20100110/bin/../lib/gcc/avr/4.3.3/../../../../avr/lib/avr5/crtm16.o |
4 | 0x00000000 __vectors |
5 | 0x00000000 __vector_default |
6 | *(.vectors) |
7 | *(.progmem.gcc*) |
8 | *(.progmem*) |
9 | .progmem.data 0x00000054 0x31 eeprom_handler.o |
10 | .progmem.data 0x00000085 0x5b cat_control.o |
11 | .progmem.data 0x000000e0 0x18 switches.o |
12 | 0x000000f8 . = ALIGN (0x2) |
13 | 0x000000f8 __trampolines_start = . |
14 | *(.trampolines) |
15 | .trampolines 0x000000f8 0x0 linker stubs |
16 | *(.trampolines*) |
17 | 0x000000f8 __trampolines_end = . |
18 | *(.jumptables) |
19 | *(.jumptables*) |
20 | *(.lowtext) |
21 | *(.lowtext*) |
22 | 0x000000f8 __ctors_start = . |
usw...
Hallo! der Code ist immer dann debugbar, wenn man irgendwo min. vier nops einfügt. Es ist also vollkommen egal in welchem C-File (habe alle probiert) oder welcher Funktion (habe ich natürlich nicht probiert). Man muß also die gesamte ROM-Größe von der alten Größe bei der der Fehler auftritt um min 8 Byte "wegbringen". Geht nicht: .text 0x00000000 0x1a10 Geht: .text 0x00000000 0x1a18 Ich hab es bis zu 9 Nops probiert. Geht: .text 0x00000000 0x1a22 Anscheinend habe ich mit meinem Code zufällig genau eine Grenze getroffen, bei der der Degugger ein Problem hat. Das gibt der Compiler im Fehlerfall aus (Compiler Option -Os): AVR Memory Usage ---------------- Device: atmega16 Program: 6842 bytes (41.8% Full) (.text + .data + .bootloader) Data: 294 bytes (28.7% Full) (.data + .bss + .noinit) EEPROM: 503 bytes (98.2% Full) (.eeprom) Build succeeded with 3 Warnings... Die drei Warnings sind ungenutzte Funktionen. Falls jemand mal zufällig :-) die gleiche Codegröße hat, kann er ja berichten ob das Problem dann auch auftritt. Für mich ist das Problem nicht transparent. Spätestens wenn das Programm erweitert wird, werde ich sehen, ob das Problem dauerhaft verschwunden ist. Gruß, Danni
Hallo! Ich habe mittlerweile das Programm um einige wenige neue Funktionen erweitert und siehe da, die nops sind nicht mehr notwendig. Für mich ist und bleibt es ein Bug im Debugger (Dragon) oder im AVR Studio. Es scheint nur mit genau dieser Codegröße oder ggf. Vielfachen oder Teilern davon aufzutreten. In der Praxis tritt es deshalb vermutlich fast nie auf (=Lottogewinn:-))oder wird falsch interpretiert. Erweitert man das Programm ein wenig, ist der Fehler auch gleich wieder weg. Für mich ist das Thema damit vorerst abgschlossen. Gruß Danni
Hi >Erweitert man das >Programm ein wenig, ist der Fehler auch gleich wieder weg. Für mich ist >das Thema damit vorerst abgschlossen. Der Dragon ist doch mittlerweile doch schon etwas verbreiteter. Wieso tritt das Problem anscheinend nur bei dir auf? Würde mir zu denken geben. MfG Spess
Hi Nachtrag: Wenn du wirklich meinst einen Bug gefunden zu haben, dann wäre Atmel die richtige Anlaufstelle und nicht dieses Forum. MfG Spess
spess53 schrieb: > Hi > > Nachtrag: Wenn du wirklich meinst einen Bug gefunden zu haben, dann wäre > Atmel die richtige Anlaufstelle und nicht dieses Forum. > > MfG Spess Das kann er sich sparen, er ist höchstwahrscheinlich nicht der erste: http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=95245 Tassilo
@ Tassilo, Super. Vielen Dank für die Info! Das ist exakt was ich vermutet habe. Also doch ein Bug. Allerdings sehe ich keinen anderen Workaround als den, den ich bereits gemacht habe (Code-Größe verändern). Da in dem genannten Beitrag andere Codegrößen genannt wurden, denke ich (wie vermutet), daß das Problem auch bei irgendwelchen Vielfachen auftritt. Ob Atmel davon weiß und/oder ob ein Bugfix geplant ist würde ich auch gern wissen, allerdings kann ich auch mit dem Workaround leben. @all Noch was: Eigentlich ignoriere ich unqualifizierte Kommentare einfach, denn die führen nur zu endlosen Diskussionen. Hier eine Ausnahme, weil sie für mich ein Beispiel sind für die "Stimmung" in manchen (wenigen) Postings: 1. >Der Dragon ist doch mittlerweile doch schon etwas verbreiteter. Wieso >tritt das Problem anscheinend nur bei dir auf? >Würde mir zu denken geben. Hat sich wohl erledigt. Ich behaupte ja auch nicht, daß Du der Einzige bist, bei dem das Problem nicht auftritt, weil Dein Code nie die 20 Byte Grenze überschritten hat. ;-) 2. >Vielleicht solltest du dich mal über den Unterschied zwischen EEMEM und >PROGMEM schlau machen. Das AVR-STudio ist mit Sicherheit bugfreier als >dein Programm. Ich denke, da weiß ich sehr gut Bescheid, weil mein Programm bisher fehlerfrei läuft. War ja auch kein EEPROM- oder Programmfehler, sondern ein AVR-Bug. Zugegebend, die von mir gezeigte ROM/EEPROM-Pointer-Stuktur ist für das ungeübte Auge verwirrend. 3. >Nachtrag: Wenn du wirklich meinst einen Bug gefunden zu haben, dann wäre >Atmel die richtige Anlaufstelle und nicht dieses Forum. Nein, diese Forum soll Anderen helfen ähnliche Probleme zu identifizieren und ggf. einen Workaround zu finden. Mir hat letztlich die Antwort von Tassilo einen Bestätigung gegeben. Natürlich kann jetzt auf AVR zugegangen werden, was bei der Häufung der Probleme vermutlich aber bereits geschehen ist. 4. >Nein. Du hängst deinen Sourcecode als Dateianhang an deinen nächsten >Post. >Oder glaubst du irgend jemand hat Lust, sich durch den grauenhaft >zusammenkopierten Text durchzuwühlen? Dieser Befehlston ist absolut inakzeptabel. Das ist Kasernenplatz-Stil. Auch wenn das Anliegen dahinter berechtigt ist, kann man es auch anders sagen. Ich verbuche es mal unter "German Directness". Ich bin relativ neu hier im Forum aber nicht neu in der Embedded-SW-Entwicklung und war bisher immer nur lesend unterwegs. Leider ist mir der Stil mancher (zum Glück weniger) Kommentare sehr negativ aufgefallen. Es wird gemeckert und die Kompetenz des Schreibers angezweifelt oder es wird sich überheblich profiliert und andere lächerlich gemacht. Schade, in englischen Foren ist der Ton meist kollegialer. Gruß Danni
Hallo Danni, nutzt Du ausschließlich AVR Studio 4 oder auch die neue Version 5? Mich würde interessieren ob Du den Bug auch mit AVR Studio 5 nachstellen kannst? Ich kann es leider nicht selbst testen, da ich (noch) keinen Dragon besitze... Viele Grüße TheChief
@Danni: Lass dich nicht von diesen Leuten nerven, leider hat sich das mittlerweile im Forum so eingebürgert das oftmals die Hälfte der Antworten aus gemeckere besteht.... Aber SEHR GUT dass du diesen Fehler hier beschrieben hast, ich hatte auch schon das gleiche Problem und weiß jetzt dass es nicht an meiner Schaltung liegt. Wenn mein Atmega88 relativ voll war ging das Debuggen ebenfalls nicht mehr. Nach einiger Zeit und einigen Codezeilen mehr wollte es wieder laufen. Hab das erstmal auf zu lange Kabel, leichte ESD,Überspannungs,was-auch-immer-Schäden usw. geschoben aber konnte bisher nie den Grund finden. Also nochmal danke für den Thread hier, das wird mir in Zukunft viel Zeit ersparen! :-)
@Markus G. > nutzt Du ausschließlich AVR Studio 4 oder auch die neue Version 5? Nur die 4er. > Mich würde interessieren ob Du den Bug auch mit AVR Studio 5 nachstellen > kannst? Es ist mir nicht klar, ob der Dragon oder das Studio den Bug hat. Ich habe mir zwar mal das Studio 5 runtergeladen, bisher aber noch nicht installiert. Z.z. ist mir mein Projekt wichtiger, als mich wieder an eine neu Toolumgebung zu gewöhnen. Ich will mir erst mal das neuste Studio 4 3.3.0 installieren. Vielleicht ist der Bug da gefixt. Im Moment tritt er ja nicht mehr auf, weil meine Codegröße verändert ist. > Ich kann es leider nicht selbst testen, da ich (noch) keinen Dragon > besitze... Dann hol ihn Dir. Ist ein tolles Teil. Gruß Danni
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.