Hallo, ich benutze globale variablen um werte aus C-Programmen heraus an Assemblerfunktionen zu übergeben. (z.B. volatile uint8_t swap1) Zum Debuggen nehme ich das AVRStudio. Setzt man nun swap1 in die Watchlist behauptet das Studio diese Variable würde sich an einer Adresse oberhalb 0x800000 (8388608) also jenseits der 8KByte befinden und gibt als Value "Invalid location" an. Meines erachtens hat der ATMEga128 aber nur 4Kbyte SRAM. Wie kommt das? Desweiteren habe ich das Problem, dass der Austausch zwischen c und Assembler auf diese Weise mal funktioniert und mal fehlschlägt. In einem kleinem Testproblem funktioniert es fehlerfrei. In einem anderen Programm, habe ich die globalen Variablen zum Datenaustausch nachträglich eingebaut, allerdings kommt bei der hälfte davon nicht der korrekt wert im Assembler an. Ausserdem will es mir nicht gelingen, den Fehler in dem Testprogramm zu reproduzieren... Ich würde gern, die seltsamen Adressen als Fehlerquelle ausschliessen. Cheers, Leif
Ich habe die "Fehlerquelle" durch systematisches auskommentieren lokalisiert. Allerdings werde ich nicht recht schlau daraus. Alles unwichtige habe weggeschnitten. Hier die kleinen Häufchen Code, die den Fehler festhalten: ////// dasproblem.c ////////// #include <avr/io.h> volatile uint8_t dummy; volatile uint8_t swap1; volatile uint8_t swap2; volatile uint8_t swap3; volatile uint8_t swap4; volatile uint8_t swap5; volatile uint8_t swap6; volatile uint8_t startadresshA0; volatile uint8_t startadresslA0; volatile uint8_t startadresshA1; //<--- HERE !!!!!!!!!!!!!! volatile uint8_t startadresslA1; volatile uint8_t startadresshB0; volatile uint8_t startadresslB0; volatile uint8_t startadresshB1; volatile uint8_t startadresslB1; volatile uint8_t startadresshC0; volatile uint8_t startadresslC0; volatile uint8_t startadresshC1; volatile uint8_t startadresslC1; volatile uint8_t startadresshC2; volatile uint8_t startadresslC2; volatile uint8_t startadresshC3; volatile uint8_t startadresslC3; extern void swapit(); extern void multi(); int main (void){ swap1 = 0xAF; swap2 = 0xFA; swap3 = 0xCF; swap4 = 0xCF; swap5 = 0xDA; swap6 = 0xDB; multi(); return(0); } ;;;;;;;;mul.S;;;;;;;;;;;;;;;;;;;; .stabs "",100,0,0,multi .stabs "mul.S",100,0,0,multi ;;#include "avr/io.h" .extern dummy .extern swap1 .extern swap2 .extern swap3 .extern swap4 .extern swap5 .extern swap6 .extern startadresshA0 .extern startadresslA0 .extern startadresshA1 .extern startadresslA1 .extern startadresshB0 .extern startadresslB0 .extern startadresshB1 .extern startadresslB1 .extern startadresshC0 .extern startadresslC0 .extern startadresshC1 .extern startadresslC1 .extern startadresshC2 .extern startadresslC2 .extern startadresshC3 .extern startadresslC3 .global multi .func multi multi: ;;;;;;;;Initialise;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cli ; disable interrupts push 18 push 19 push 20 push 21 push 22 push 23 push 24 in 24,0x3F ;SREG push 24 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; lds 18, swap1 lds 19, swap2 lds 20, swap3 lds 22, swap4 lds 23, swap5 lds 24, swap6 ;;;;;;;;;;;;;;;;;cleanup;;;;;;;;;;;;;;;;;;;;;;;; pop 24 out 0x3F, 24 ;SREG pop 24 pop 23 pop 22 pop 21 pop 20 pop 19 pop 18 sei ; Enable interrupts ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ret .endfunc Compilen und linken übernimmt die Stapelverabrbeitung im Anhang. Der Fehler im Detail: Die Variable swap4, wird mit 0xCF initialisiert. Da sich die Variable nicht mit der "watchlist" überwachen lässt, lade ich sie testhalber in das Register 22. Dort erscheint leider der wert 0xC0. Alle anderen swaps geben die korrekten werte in die Register. Tauschen der Register oder der Reihenfolge ändert nichts: swap4 liefert den falschen wert. Der Fehler lässt sich beheben indem man die mit "HERE !!!!!!!!!" Kommentierte Zeile auskommentiert. Kann sich da Jemand einen Reim draus machen?! Cheers, Leif
Anstelle die Zeile auszukommentieren kann man auch der Variablen dort einen anderen Namen geben. Ich werd einfach nicht schlau daraus... Ich hoffe Irgendjemand hat eine Idee. Cheers, Leif
Nur ne Idee: Evtl. doppelte Deklaration der startadresshA1-Variablen im Code?
In welchem Zusammenhang stehen startadresshA1 und swap4? Oder gibt es keinen und das ist das Problem?
Aber wie gesagt, man kann hiernur raten. Ich denke Du würdest mehr Info's bekommen, wenn Du das ganze Projekt zur Verfügung stellst.
Es gibt keinen Zusammenhang zwischen den Variablen. Ich kann zumindest keinen erkennen. Die obigen quelltexte sind das Projekt. Der einfach halt halber habe ich die entsprechenden Dateien angehängt. doit.bat compiliert, linkt und wandelt anschliessen ins COFF Format, vorausgesetzt WinAVR ist installiert. (Einfach mit Enter bestätigen, es sind pausen dabei um eventuelle Ausgaben lesen zu können) Das .cof lässt sich dann mit dem Studio debuggen.
Ok, nur die Sourcen betrachtet sehe ich den Fehler auch nicht. Da ich mit der WinArm-Umgebung für einen anderen µC programmiere, kann ich Dein Beispiel nicht direkt kompilieren. Ich könnte es zwar mit dem arm-elf-gcc probieren. Fraglich ist nur, ob wir dann das gleiche Ergebnis erhalten. Eine Möglichkeit ist evtl. noch, dass Du mir die elf.Datei zukommen läßt. Diese kann ich dann mal mit objdump und Co. analysieren. Vielleicht sehe ich ja dann was.
Oder Du linkst mal mit der Option -Xlinker -Map=dasproblem.map und schickst dann die map-Datei.
Ok ich bin ein wenig weiter. Die Zeile lds 22, swap4; sieht im Disassembler wie folgt aus: 35: swap4 = 0xCF; +00000057: EC8F LDI R24,0xCF Load immediate +00000058: 93800068 STS 0x0068,R24 Store direct to data space Im extenden I/O Memory kann man die geschrieben werte beobachten. swap4 wird zunächst mit 0xCF korrekt in den SRAM geschrieben. Der übernächste Befehl ist swap5 = 0xDA; im Disassembler zu sehen als: 38: startadresshC3= 0xDE; +0000005D: ED8E LDI R24,0xDE Load immediate +0000005E: 93800067 STS 0x0067,R24 Store direct to data space STS 0x0067,R24 Überschriebt 0xCF mit 0xC0 Deshalb verschwindet das Problem wenn man etwas an den Variablem rumspielt: Die variablen stehen an anderen Stellen im Speicher. Bei bestimmten kombinationen überschreiben sie sich nicht gegenseitig. (Umbenennen von startadresshA1 in startaaaaadresshA1 hilft zum Beispiel) Nur warum geschieht die überhaupt?! Zum selbernachschauen habe ich das .elf angehängt. Sind die GNU-Tools buggy oder habe ich da bösen C-Code geschrieben?! Cheers, Leif
Ist das auf einem realen AVR oder auf einem Simulanten^H^H^H^Htor? Wenn letzteres, ist dir schon mal in den Sinn gekommen, dass sowas auch nur Software ist, die Bugs haben kann? Der (Dis-)Assemblercode sieht jedenfalls OK aus.
So ich hab mal einen Blick in Dein Map-File geworfen. Das Deine Variablen oberhalb von 0x00800000 liegen ist korrekt und hat nichts mit der Speicher-Kapazität des ATMEGA zu tun. Sondern mit dem eingestellten Speicher-Mapping. Siehe Dazu Auszug aus Deinem Map-File: Memory Configuration Name Origin Length Attributes text 0x00000000 0x00002000 xr data 0x00800060 0x0000ffa0 rw !x eeprom 0x00810000 0x00010000 rw !x default 0x00000000 0xffffffff Wie Du dort sehen kannst beginnt der Speicherbereich für Deine Daten ab der Adresse 0x00800060 und hat die Länge 0x0000ffa0. Deine Variablen liegen an folgenden Adressen: 0x00800060 swap3 0x00800061 startadresslC2 0x00800062 startadresshA1 0x00800063 swap5 0x00800064 startadresshC1 0x00800065 startadresslC1 0x00800066 swap6 0x00800067 startadresshC3 0x00800068 swap4 0x00800069 startadresslC3 0x0080006a startadresslA1 0x0080006b startadresshA0 0x0080006c swap1 0x0080006d startadresslB1 0x0080006e startadresshB0 0x0080006f startadresslA0 0x00800070 startadresslC0 0x00800071 swap2 0x00800072 startadresshC2 0x00800073 startadresslB0 0x00800074 dummy 0x00800075 startadresshB1 0x00800076 startadresshC0 und somit auch korrekt im Speicherbereich für Daten. Wenn Dein Debugger nun der Meinung ist, dass sich die Daten an einer ungültigen Position befinden, dann ist dies doch schon sehr fragwürdig. Außerdem habe ich versucht mit arm-elf-objdump den DisassemblerCode Deines Programmes anzuschauen. Ist jedoch scheinbar nicht möglich. arm-elf-objdump stieg mit der Fehlermeldung aus: Can't disassemble for architecture UNKNOWN! Ist auch nachvollziehbar! Es wäre jetzt noch möglich mit der Option -S zu kompilieren um nur den Assembler-Code zu sehen und hier reinzustellen. Aber wie Jörg schon sagte, scheint das hier wirklich ein Problem Deiner Entwicklungsumgebung zu sein.
Simulator des AvrStudios... Könnte natürlich auch daran liegen. Das Problem besteht dann jedoch weiterhin :( Ich werde mal bei Atmel nachfrqagen. Danke soweit!
Hmm Atmel nach dem AVRStudio fragen... Das Studio wird von SourceForge gehostet. Dort stehen Eric Weddington und Jörg Wunsch als Admins. Da bin ich hier doch gar nicht so schelcht aufgehoben. Weil es schon ein paar Tage her ist, fasse ich nochmal zusammen: Ich habe ein Assemblerprogramm, welches mittels volatile/extern deklarierten variablen adressen übergeben bekommt. Leider überschreiben sich die Zeiger gegenseitig wenn sie in den SRAM geladen werden. (Im angehängten Code wird swap4 überschrieben, wenn swap6 in den SRAM geladen wird.) Gibt man den Zeigern neue Namen oder lässt einen weg (z.b. bei startadresshA1) verändern sich beim nächsten compilieren die adressen der Zeiger. Das kann dazu führen, daß sich zufällig eine verteilung ergibt in der sich die Zeiger nicht überschreiben. Leider führt auch Weiterstricken des Codes dazu, daß bei nächsten Compilieren andere Adressen verteilt werden und das Problem taucht irgendwann wieder auf. Gegenseitig überschreiben sich nur Variablen mit dem qualifier "volatile". Das Problem lässt sich zweifelsfrei reproduzieren, auch auf anderen Computern mit einer älteren Version des Studios. Um zweifelsfrei zu klären ob es, wie von Karsten und Jörg vermutet tatsächlich am Simulator liegt, würde ich mich freuen wenn Jemand das programm in einem anderem Simulator laufen lassen könnte. Im anhang ist das Programm in Form von Quellcode, als .cof und als .elf. Ein .map file liegt auch bei. Gruß, Leif
Stimmt! Trotzdem wäre mir wohler wenn ich genau wüsste, daß es am Studio liegt...
Überlässt man complilieren und linken dem Studio, verfliegt das Problem anscheinend. Die volatile variablen landen dann auch in einem ganz anderen Speicherbereich. Warum bringt der Linker bei händischem Aufruf meinerseits die volatlie variablen (und nur diese) eigentlich an den 0x800.. adressen unter? Für alle andere Variablen beginnt der SRAM bei 0x100. Und wie kann ich darauf einfluß nehmen?
Die 0x800000 ist der Offset, den der RAM-Bereich intern bekommt. Der EEPROM bekommt 0x810000. Damit werden die drei Speicherbereiche des AVR sozusagen virtuell in einen flachen Adressraum abgebildet, weil das das Einzige ist, was die GNU-Tools derzeit verstehen.
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.