Hallo Leute! Ich arbeite hier mit einbem Atmel ATMega16 und AVR-GCC. Folgendes Problem: Wenn eine ISR aufgerufen wird, müsste ja die Rücksprungadresse auf den Stack gelegt werden. Allerdings landet da nur Schwachsinn! Ich werd total wahnsinnig ^^ Hier mal die Details: Sofort am Anfang der ISR steht der StackPointer auf 0x03D9. An dieser Stelle steht dann im SRAM eine 0x247D. Und dieser Wert ist natürlich jenseits von Gut und Böse (der Speicher geht ja maximal bis 0x1FFF). Ein sinnvoller Wert wäre eher 0x0451, denn da liegt die Funktion die unterbrochen wurde... Kennt sich Jemand damit aus? Hab ich da irgendwo einen Denkfehler? Such ich die Rücksprungadresse an der falschen Stelle? Oder lese ich sie nur falsch? Danke für eure Hilfe!
Sorry, ich seh gerade, dass ich das falsche Forum erwischt hab. Kann das Jemand verschieben? Danke! :-)
und in welches Forum willst Du verschoben werden? Werden eventuell noch Register (Status etc.) auf den Stack gepusht?
Wenn der Stack Pointer am Anfang der ISR (also wenn die Adresse bereits gesichert wurde) auf der von Dir besagten Adresse steht, dann liegt der gerettete Programmzähler-Wert zwei Bytes weiter oben. Schließlich wird erst die Adresse gesichert und dann der Stack-Pointer dekrementiert. Andernfalls wüsste der Stack-Pointer ja nie, ob er jetzt um eins (push) oder um zwei (Adresse retten) dekrementiert werden müsste. Da wo der Stack Pointer aktuell hinzeigt, ist die Stelle, an der der nächste zu sichernde Wert abgelegt würde, wenn er kommt. Also: Interrupt/Funktionsaufruf tritt auf -> PC wird an Adresse von Stack Pointer geschrieben, Stack Pointer wird um zwei dekrementiert. ret(i) tritt auf -> Stack Pointer wird um 2 inkrementiert, Adresse wird in PC geschrieben. Ergo: Die Reihenfolge ist wichtig. Schau mal an der Adresse 0x03db (SP + 2), da könnte was sinnvolles stehen... An der Adresse, auf die der SP aktuell zeigt, steht fast immer Murks.
Oder lies mal unmitelbar NACH einem RET(i) die Stelle aus, wo der SP hinzeigt...
Danke erstmal für eure Antworten! Schön, dass es noch andere Leute gibt, die sich so tief in die Hölle hinabwagen ;-) Ich habe mir natürlich auch schon den gesamten Speicher um den StackPointer herum angesehen. Da ist nirgendwo etwas, was der gewünschten Rücksprungadresse ähnlich sieht. Das verrückte ist aber, dass er beim RETI trotzdem an die richtige Stelle zurückspringt!!! Wah! Hier noch mehr Details: StackPointer in der ISR: 0x3D9 StackPointer nach dem Rücksprung: 0x3DB ProgramCounter nach dem Rücksprung: 0470 Aber diese 0470 ist nirgendwo im Speicher (in der nähe des StackPointers) zu sehen: http://img215.imageshack.us/img215/3097/memoryui2.jpg Irgendwas sehe ich da wohl falsch, weil der Rücksprung ja anscheinend funktioniert....
Hallo Josch, sprechen wir hier über Assembler-Programm oder Hochsprachen- compilierte Anwendung? Letztere nutzt den Hardware-Stackpointer in völlig anderer Manier als ein simples Assembler-Programm. Compiler verwalten einen eigenen Stackbereich, schon weil der Hardware-Stack- pointer bei Manipulationen über SPL- und SPH-Register nicht solide Interrupt-fest ist.
>ProgramCounter nach dem Rücksprung: 0470
Wie hast du denn diese Werte ausgelesen?
Kannst du mal etwas von deinem Quellcode posten? Den du zum Test
verwendest?
Gast wrote: > Hallo Josch, > sprechen wir hier über Assembler-Programm oder Hochsprachen- > compilierte Anwendung? > Letztere nutzt den Hardware-Stackpointer in völlig anderer > Manier als ein simples Assembler-Programm. Compiler verwalten > einen eigenen Stackbereich, schon weil der Hardware-Stack- > pointer bei Manipulationen über SPL- und SPH-Register nicht > solide Interrupt-fest ist. Mal abgesehen von ein paar Sachen im Offtopic-Forum ist das der größte Blödsinn, den ich hier heute gelesen habe... Da die gesamte Stack-Verwaltung im AVR durch die Hardware geschieht, bleibt auch einem noch so tollen Compiler nichts anderes übrig, als die Programmzählergeschichten der Hardware zu überlassen. Und dass der Hardware-Stackpointer "nicht Interrupt-fest" sein soll, ist völlig daneben...
Ich sehe jetzt das Problem irgendwie nicht. Wenn korrekt zurückgesprungen wird, warum interessiert dich das dann überhaupt? PS: Hast du auch daran gedacht, daß der Programmspeicher 16bittig adressiert wird, die Toolchain aber in der Regel Aderssen auf 8-bit-Basis anzeigt?
@ Matthias L.: "Wie hast du denn diese Werte ausgelesen?" Im Processor View von AVR Studio kann ich den PC ablesen. Ich hab also direkt hinter den Rücksprung einen Breakpoint gesetzt, und voila! "Kannst du mal etwas von deinem Quellcode posten? Den du zum Test verwendest?" Na sicher ;-) Funktion, die unterbrochen wird: while(1) { lcd_writeChar('.'); delayMs(100); }//end while ISR (Timer compare match): void SIG_OUTPUT_COMPARE1A( void ) { asm volatile("reti \n\t"); } @ Rolf Magnus: "Ich sehe jetzt das Problem irgendwie nicht. Wenn korrekt zurückgesprungen wird, warum interessiert dich das dann überhaupt?" Das hat verschiedene Gründe. Erstens würde ich gerne VERSTEHEN, was da passiert. Ich muss das ganze nämlich später anderen Leuten beibringen, und da sind solch grobe Verständnisprobleme sicher nicht gut! Zweitens klappt es nicht immer. Wenn ich das Programm ein bisschen komplexer mache, fängt das System an, wild rumzuspringen, und alles kaputt zu machen. Deswegen würde ich gerne genau wissen, was es mit diesen komischen Adressen auf sich hat, und wo sich die "echte" Rücksprungadresse versteckt....
Hallo, mich wundert dein reti befehl an dieser Stelle: void SIG_OUTPUT_COMPARE1A( void ) { asm volatile("reti \n\t"); } Wird das nicht vom Compiler selber erledigt ? Wäre mir völlig neu, habe selber schon Interrupts benutzt. Sonst haste 2 mal reti im Programm und der Prozessor würde nur noch Amok laufen. ( Compiler gcc ?) Jogibär
Vieleicht würde es auch ohne gehen, aber der fürhrt garantiert nur ein Reti aus. Das kann man ja mit Single-Steps gut Debuggen :-) Müsste also OK sein!
Hallo, nach mal nachgedacht. Ja, er führt nur das erste reti aus -> aber das falsche. Bei Interrupteinsprüngen wird nicht nur die Rücksprungadresse auf den Stack geschrieben, sondern mindestens noch das Prozessorzustandswort. (Flags wie carry u.s.w.) (Der GCC sichert manchmal noch mehrere Register mit) Bei deinem reti holt er bestimmt nicht die Adresse zurück, oder kommt nach mehrmaligem Aufruf durcheinander. Kannst Du mal den Assemblercode posten ? Da müßte man es sehen. Jogibär
Aber müsste dann nicht wenigstens IRGENDWO die richtige Adresse im Speicher zu sehen sein?
Hallo, darum bitte ich ja auch um den Assemblercode. Jogibär
> void SIG_OUTPUT_COMPARE1A( void ) > { > asm volatile("reti \n\t"); > } Wenn das ne ISR sein soll, dann entspricht die aber nicht der AVR-GCC-Syntax! Außerdem (also wenn die Syntax richtig wäre) würde das sowieso schiefgehen, wie schon von anderen vermutet. Das führt ein reti aus, bevor das SREG und die ganzen anderen Register, die der Compiler am Beginn der ISR sichert, wieder zurückgeschrieben wurden. In dem Moment, in dem das reti hier ausgeführt wird, steht alles Mögliche auf dem Stack, nur ganz bestimmt nicht die richtige Rücksprungadresse! Das reti steckt in der schließenden Klammer "}" mit drin. Da aber die Syntax völlig daneben ist, wird diese ISR vermutlich eh nie ausgeführt...
Hallo Johannes, > Mal abgesehen von ein paar Sachen im Offtopic-Forum ist das der größte > Blödsinn, den ich hier heute gelesen habe... > Da die gesamte Stack-Verwaltung im AVR durch die Hardware geschieht, > bleibt auch einem noch so tollen Compiler nichts anderes übrig, als die > Programmzählergeschichten der Hardware zu überlassen. Und dass der > Hardware-Stackpointer "nicht Interrupt-fest" sein soll, ist völlig > daneben... Nun ja, mit 30 Jahren CPU-Programmiererfahrung - davon seit 1997 auch auf AVR - weiß ich natürlich nicht, wovon ich schreibe. ;-)
@Gast: Schau Dir einfach mal ein compiliertes AVR-C-Programm an... Ist übrigens immer wieder toll, was Leute, die sich originellerweise "Gast (Gast)" nennen, hier erzählen...
Disassaembler (ab der Stelle wo Interrupts eingeschaltet werden): 265: sei(); +0000046B: 9478 SEI Global Interrupt Enable 270: delayMs(os_taskOutputDelay); +0000046C: 91C00062 LDS R28,0x0062 Load direct from data space +0000046E: 91D00063 LDS R29,0x0063 Load direct from data space 269: lcd_writeChar('.'); +00000470: E28E LDI R24,0x2E Load immediate +00000471: 940E0201 CALL 0x00000201 Call subroutine +00000473: 01CE MOVW R24,R28 Copy register pair +00000474: 940E0108 CALL 0x00000108 Call subroutine +00000476: CFF9 RJMP PC-0x0006 Relative jump @00000477: __vector_6 55: { +00000477: 9518 RETI Interrupt return Der Interrrupt ist naked, daher gibt's da auch nicht mehr zu sehen. Hat im übrigen schon sehr gut und zuverlässig in einem anderen Projekt funktioniert (copy & paste). Wäre dem Topic vielleicht dienlich, wenn kein geflame ausbräche... THX ;-)
"Im Processor View von AVR Studio" ... hm... weiß der Geier, was das Ding anzeigt. Wenn ichs unbedingt wissen will würde ich mir lieber die SPH und SPL-Registerinhalte zwischenspeichern und via RS232 ausgeben lassen. Interruptfunktionen werden so definiert: ISR (TIMER1_COMPA_vect) { // hier Code einfügen return; } und damit funktionierts...
Hallo Josh, > void SIG_OUTPUT_COMPARE1A( void ) > { > asm volatile("reti \n\t"); > } der Compiler erzeugt zu jeder Funktion eine eigene Stack- Umgebung. Ein "reti" innerhalb einer Funktion führt zu fehlerhaftem Programm-Verhalten - im besten Falle läuft der Kellerspeicher irgendwann über.
Ich meinte: Den Inhalt des Stacks, auf den den SP zeigt ,-)
Aber da die Funktion ja als naked deklariert ist, sollte doch genau das nicht passieren?
Was genau macht denn diese Schreibweise: "ISR (TIMER1_COMPA_vect)" anders als meine? //! ISR for timer compare match (scheduler) void SIG_OUTPUT_COMPARE1A( void ) _attribute_ ( ( signal, naked ) ); ??? Hö?? ;-)
Sorry, wenn Du hier unvollständigen Code schickst, in dem wichtige Dinge fehlen, dann brauchst Du Dich echt nicht zu wundern. In Deinem ersten Codeschnipsel stand nichts von "__attribute__..."!
Das ist ja auch nur im Header, daran hatte ich nicht gedacht. Sorry!
Hallo Johannes, > Und dass der > Hardware-Stackpointer "nicht Interrupt-fest" sein soll, ist völlig > daneben... Selbstverständlich ist der 16-bit-Stackpointer SPH, SPL bei Manipulationen der Register über 8-Bit-Befehle nicht interrupt-fest. Genau deshalb werden für Timer, A/D und andere 16-Bit-Register high- und low-byte gelatcht. Dies ist für Stackoperationen mit SPH und SPL nicht der Fall. Die Polemik ist fehl am Platz - ob ein Beitrag hier falsch oder richtig ist, hat mit dem Namen nichts zu tun.
@Josch: Du hast die ISR mit _attribute_ ( ( signal, naked ) ) deklariert. Das sind zwei unterschiedliche, und auch gegensätzliche Dinge. Gerade, was das Stackaufräumen betrifft: Naked macht da garnichts, während eine Signal-Funktion... etliche Register pusht und popt. ISR ist in interrupt.h als #define ISR(vector) \ void vector (void) _attribute_ ((signal)); \ definiert. Und nicht naked!
Hallo, kommt mal langsam wieder zurück auf den Boden. ansonsten schau da mal rein Beitrag "attribute" zu signal und nacked gleichzeitig Bin leider nicht der Crack im__attribute__ Zeugs. Der KOMPLETTE Assemblercode VOM gcc wäre mir lieber. Jogibär
Ich denke, du hast einfach nur vergessen, dass die Rücksprungadresse als 16-bit-Wortadresse auf dem Stack landet, also gegenüber der Byteadresse durch 2 geteilt. Ansonsten habe ich selbst schon hinreichend ``post mortem''-Analysen an AVR-Programmen gemacht um dir sagen zu können, dass die da wirklich auf dem Stack steht. ;-) Man muss natürlich ggf. mit dem Disassembler für die jeweilige Funktion nachgucken, welche Register alles auf dem Stack landen und ob ggf. noch Platz für lokale Variablen eingeräumt wird. Die kann man aber alle fein säuberlich abzählen, dann findet man auch die Rücksprungadresse. Im Gegensatz zu anderen Architekturen ist der Stack des AVR ein post-decrement, er wird als sinngemäß als
1 | *sp-- = value_to_push; |
beschrieben und als
1 | value_to_pop = *++sp; |
gelesen. Daher wird der Stack auch auf die oberste RAM-Zelle initialisiert.
Genau, alle wieder beruhigen :-D Ich habe euren Vorschlag die ISR zu ändern jetzt mal umgesetzt ("ISR (TIMER1_COMPA_vect)"). Ausserdem habe ich das böse Reti weggenommen. Das Problem besteht allerdings weiterhin: Es wird jetzt jede Menge Zeug auf den Stack geworfen, wenn der Interrupt auslöst. Vorher waren es nur 2 Byte, jetzt sind es 18. Aber immernoch ist in diesen 18 Byte die Rücksprungadresse nicht zu erkennen. Trotzdem springt er dann am Ende der ISR brav wieder zurück... komisch! Hier nochmal die Adresse an die er aus der ISR springt: 0x00047F. Der StackPointer bewegt sich im Bereich 0x03DB (vor dem Sprung in die ISR) bis 0x03C9 (Sofort am Anfang der ISR). Und hier der Speicher: http://img225.imageshack.us/img225/4249/memory2xv6.jpg Besagter Bereich (in dem die ADresse zu finden sein sollte) ist markiert.
Josch wrote: > Der Interrrupt ist naked, daher gibt's da auch nicht mehr zu sehen. Hat > im übrigen schon sehr gut und zuverlässig in einem anderen Projekt > funktioniert (copy & paste). Daß etwas scheinbar einmal funktioniert hat, ist ne null Aussage. Wenn Du naked benutzt, dann bist Du auch für die Registersicherung verantwortlich und die fehlt hier !!! Mindestens SREG, R24,25,28,29 werden zerstört. Dein Main wird also durch den Wolf gedreht, kein Wunder, daß dann nichts mehr funktioniert. Außerdem macht naked nur Sinn, wenn der Interrupt kurz ist, z.B. nur nen Portpin setzen. Hier aber wird stundenlang gewartet und schnarchlahme LCD-Ausgabe gemacht, die gesparten PUSH/POP bringen daher überhaupt nichts. Peter
@Peter: Darum geht es mir im Moment garnicht. An die Registersicherung habe ich schon gedacht, aber da sie im Moment nicht wichtig ist, hab ich sie rausgenaommen. Es interessieren mich wirklich nur die Rücksprünge! (siehe meinen letzten Post) Danke trotzdem für die Infos!
Ich vermute mal, deine 0x451 (letzte beide Bytes des markierten Bereichs) sind die Rücksprungadresse. Liegt halt ein wenig vor der von dir genannten. AVR Studio hält nur an den Grenzen der `high level instructions', also der C-Zeilen an. Was ich oben noch vergessen hatte: die PC-Adresse auf dem Stack ist, im Gegensatz zu vielen anderen Dingen beim AVR, big-endian. :-o
Gast wrote: > Selbstverständlich ist der 16-bit-Stackpointer SPH, SPL bei > Manipulationen der Register über 8-Bit-Befehle nicht interrupt-fest. > Genau deshalb werden für Timer, A/D und andere 16-Bit-Register > high- und low-byte gelatcht. > Dies ist für Stackoperationen mit SPH und SPL nicht der Fall. Der Stack-Pointer wird aber auch i.d.R. durch das Programm nur ein einziges Mal manipuliert, nämlich bei der Initialisierung bei Programmstart. Deshalb ist es im Normalfall völlig unerheblich, dass es sich um ein 16-Bit-Register handelt. Wenn man die Hardware alles machen lässt, wofür sie die Möglichkeiten hat, gibt es auch keine Probleme!
Das dachte ich auch schon. Aber ich habe da mal angehalten, Müll in diese Speicherstelle reingeschrieben, und dann einen Single-Step gemacht. Er landet nach wie vor an der selben Stelle. Von daher muss die Adresse wo anders liegen.... nerv
OK, ich glaube ich hab's. Das Problem ist, dass AVR Studio Einfach manche Speicherstellen falsch anzeigt beim Debuggen. Das kann echt verwirren ^^ Vielen Dank euch allen!
Muha, zu früh gefreut! Leider zeigt AVR Studio den Speicher doch richtig an. Aber dafür bin ich der Lösung des Problems jetzt ein gutes Stück näher. Die Adresse lautet 0x00047D, aber im Speicher steht ..00 24 7D 00... Wo kommt da bitte die 2 her? Wäre das eine 0, wäre alles in Butter :-)
Hallo Johannes, so, und nachdem die Polemik ein wenig zurück gefahren wurde und vielleicht zugestimmt wird, dass der 16-bit-Stackpointer bei AVR keineswegs interrupt-fest ist, sind wir vielleicht auch zugänglich zu dem Gedankengang, den "Nixblicker" und "Blödsinn-Erzähler" Gast bei seinem ersten Statement im Sinn hatte. Da speziell bei AVR der Stackpointer nicht interrupt-fest ist, verbieten sich anderweitig gern benutzte Stackoperationen der Art "ADD/SUB SP+x" um Variable über den Stack an Funktionen zu übergeben oder einfach nur eine lokale Funktions-Umgebung zu schaffen. Abhilfe schafft ein eigener "Software-Stack", über den durchaus auch Rückkehr-Adressen verwaltet werden können. Erst mit einem solchen "Software-Stack" lassen sich die C-style X,Y,Z-pointer- Operationen sinnvoll nutzen. Dazu müssen diese Pointer-Register aber wiederum im Hardware-Stack gesichert werden. Was der ganze Roman soll? Nun ja, anfangs stand ja im Raum, dass es unerklärliche Inhalte im Hardware-Stack-Bereich geben sollte. Nicht mehr und nicht weniger. Und da ist es eben nicht zwingend so, dass dort nur return-Adressen stehen, sondern auch x-beliebige Inhalte, z.B. auch gerettete Register-Inhalte zur Verwaltung eines Software-Stack. Um nicht mehr und nicht weniger ging es. Bemerkungen wie "der größte Blödsinn" bringen in der Sache nicht weiter. Inzwischen wurden einige Sachverhalte vom Fragesteller präzisiert, was auch Raum für gezieltere Vermutungen schuf. Und letztendlich hat sich die Sache ja noch ganz anders aufgeklärt.
"Und letztendlich hat sich die Sache ja noch ganz anders aufgeklärt." Nein, noch nicht ganz! Bitte meinen letzten Post beachten! ;-)
Jörg Wunsch wrote: > Ich denke, du hast einfach nur vergessen, dass die Rücksprungadresse > als 16-bit-Wortadresse auf dem Stack landet, also gegenüber der > Byteadresse durch 2 geteilt. Hallo, wo steht denn das ? Ich habe schon im Datenblatt geschaut, aber das ist mit Infos über unser Diskussionsthema ziemlich geizig. PS: Das kann ich mir ehrlich gesagt gar nicht vorstellen. Dann muß ja die ALU ständig selber hin und her rechnen. ( oder verschieben bei /2 ). ------ Habe eben was im Datenblatt zum Mega128 gefunden: zitat': S.18 The ATmega128 Programm Counter is 16 bits wide, thus adressing the 64k programm memory location. 16 bit = 64 K das hört sich für mich nicht nach Wortadresse an. Jogibär
Hallo Josch, auch auf die Gefahr hin, von Anderen als "Blödsinn"-Erzähler geoutet zu werden ;-) - wir sehen hier nur einen Ausschnitt Deiner Codes. Kann es vielleicht sein, dass der im Listing ausgewiesenen Adresse noch ein Offset von 0x2000 für ein Code-Segment hinzuaddiert werden muss? Ganz vorsichtig und unter allen Vorhalten, nur laut gedacht...
Gast wrote: > Bemerkungen wie "der größte Blödsinn" bringen in der Sache nicht > weiter. Das ist grundsätzlich richtig, und ich gebe zu, dass es etwas unverhältnismäßig war. Es gibt hier nur dummerweise viele, die unter dem "Schutzschild-Nick" Gast (Gast) (und das ist, wie oben schon angedeutet, der unoriginellste der ganzen Troll-Nicks) allen möglichen Unsinn posten, der jeglicher fachlicher Grundlage entbehrt und nur Verwirrung und Ärgernis schaffen soll. Deshalb meine etwas "verschnupfte" Reaktion. Nachdem sich nun ja doch herausgestellt hat, dass das oben nicht zum Zweck der Verwirrung gedacht war, sollten wir das auf sich beruhen lassen...
Michael Jogwich wrote: > Habe eben was im Datenblatt zum Mega128 gefunden: > ... > das hört sich für mich nicht nach Wortadresse an. Der Mega128 hat 128KiB Flash, das sind 64Ki Worte...
Der PC vom Mega16 ist übrigens nur 13 Bit breit, d.h. die 2 da hat überhaupt keinen Einfluss auf den Wert des PC. PC: XXXP PPPP PPPP PPPP ^ Da würde das Bit für die "2" stehen... Scheint also tatsächlich alles im grünen Bereich zu sein.
Hallo Johannes, dann möchte ich meinen Beitrag zur Versöhnung nicht schuldig bleiben - "Gast" wie oben ersetzen. Wer mit "dk5ug" etwas anfangen kann, weiß meine Aus- führungen auch einzuordnen. @Josh Weiterhin viel Erfolg bei der Suche nach einer Erklärung für die unpassenden Speicherinhalte! August
August, dk5ug wrote: > Hallo Johannes, > dann möchte ich meinen Beitrag zur Versöhnung nicht > schuldig bleiben - "Gast" wie oben ersetzen. > Wer mit "dk5ug" etwas anfangen kann, weiß meine Aus- > führungen auch einzuordnen. Kann ich als nicht-Amateurfunker zwar nichts mit anfangen, aber nix für ungut... @all: Wie weiter oben gesagt, scheint die Suche aber erfolgreich zu sein. Es werden anscheinend tatsächlich nur die 13 signifikanten Bits des PC überhaupt geschrieben, in den 3 MSB des Stack-Wortes bleibt anscheinend der Müll von der letzten Benutzung stehen...
Johannes M. wrote: > Michael Jogwich wrote: >> Habe eben was im Datenblatt zum Mega128 gefunden: >> ... >> das hört sich für mich nicht nach Wortadresse an. > Der Mega128 hat 128KiB Flash, das sind 64Ki Worte... Allerdings steht im Datenblatt 64K Programm Memory 64K sind 64k egal ob 8 16 oder 32 bit breit. Den Zugriff auf den Speicher oberhalb der 64K erfolgt anscheinend anders. Ist hier glaube ich schon mehrmals diskutiert worden. Ist auch nicht unbedingt mein Steckenpferd. Jogibär
Michael Jogwich wrote: > Allerdings steht im Datenblatt 64K Programm Memory Da steht "64 K Program Memory *Locations*"! Eine "Location" ist im Zusammenhang mit dem Flash immer ein Wort. Nur beim Zugriff mit lpm, bei dem Bytes adressiert werden, muss man sich etwas einfallen lassen, um die Halbbytes anzusprechen. Dafür gibts dann die elpm-Befehle, die zusätzliche Register nutzen, um den Adressraum komplett ansprechen zu können... > 64K sind 64k egal ob 8 16 oder 32 bit breit. 64 K sind zunächst mal nur 64 * 2^10 = 65536. Ohne Einheit dahinter ist das nur eine Zahl. Und die Einheit steht in diesem Falle direkt dahinter, nämlich "Memory Locations". Genau das hast Du in Deinem "Zitat" aber anscheinend überlesen... Wenn da 64 K*B* gestanden hätte, dann hättest Du Recht gehabt.
Johannes M. wrote: > Michael Jogwich wrote: >> Allerdings steht im Datenblatt 64K Programm Memory > Da steht "64 K Program Memory *Locations*"! Eine "Location" ist im > Zusammenhang mit dem Flash immer ein Wort. Nur beim Zugriff mit lpm, bei > dem Bytes adressiert werden, muss man sich etwas einfallen lassen, um > die Halbbytes anzusprechen. Dafür gibts dann die elpm-Befehle, die > zusätzliche Register nutzen, um den Adressraum komplett ansprechen zu > können... > >> 64K sind 64k egal ob 8 16 oder 32 bit breit. > 64 K sind zunächst mal nur 64 * 2^10 = 65536. Ohne Einheit dahinter ist > das nur eine Zahl. Und die Einheit steht in diesem Falle direkt > dahinter, nämlich "Memory Locations"... Hallo, hoppla, da wirst Du wohl recht haben. Der Speicher ist organisiert in 16 Bit, das könnte stimmen. ( im Datenblatt gibt es ein paar Stellen, wo man aufpassen muß, ob die nun Wort oder Byteadressen meinen) Bloß warum wir dann immer so ein Aufriß beim Überschreiten der 64K Programmgröße gemacht ? Jogibär
Michael Jogwich wrote: > Bloß warum wir dann immer so ein Aufriß beim Überschreiten der 64K > Programmgröße gemacht ? Das ist eigentlich nur für den oben erwähnten Zugriff auf im Flash abgelegte Konstanten (z.B. Textstrings) (über den Assembler-Befehl elpm) problematisch, weil die in der lib enthaltenen Funktionen (pgm_read_byte_far() und anverwandte) in der aktuellen Implementierung nur 64 KiB adressieren können. Vom Programmcode her ist das an sich kein Problem.
Johannes M. wrote: >> Bloß warum wir dann immer so ein Aufriß beim Überschreiten der 64K >> Programmgröße gemacht ? Wird doch gar nicht, erst beim ATmega256x wird es haarig. Das Ausnutzen der 128 KiB ROM für Programmcode auf dem ATmega128 ist gar kein Problem (und war nie eins). > Das ist eigentlich nur für den oben erwähnten Zugriff auf im Flash > abgelegte Konstanten (z.B. Textstrings) (über den Assembler-Befehl elpm) > problematisch, weil die in der lib enthaltenen Funktionen > (pgm_read_byte_far() und anverwandte) in der aktuellen Implementierung > nur 64 KiB adressieren können. Gerade pgm_read_byte_far() kann mehr adressieren. ;-) Insbesondere können aber alle _P-Funktionen (strcpy_P, memcpy_P und sowas) nur mit 16-bit-Adressen umgehen, und da sie den ROM als Daten adressieren, können sie also nur 64 KiB daraus zugreifen. Wer mehr haben will, muss sich um die größere Adressierung selbst kümmern und pgm_read_*_far() benutzen. Ja, ein wenig Verwirrend ist diese Dualität des AVR-ROMs schon.
Johannes M. wrote: > Wie weiter oben gesagt, scheint die Suche aber erfolgreich zu sein. Es > werden anscheinend tatsächlich nur die 13 signifikanten Bits des PC > überhaupt geschrieben, in den 3 MSB des Stack-Wortes bleibt anscheinend > der Müll von der letzten Benutzung stehen... Das erklärt das Symptom natürlich. Wäre ich auch nicht drauf gekommen, da ich im Wesentlichen ATmega1281 benutze, bei denen natürlich immer alle Bits geschrieben werden. Aus Hardwaresicht ist das Ganze dagegen verständlich: die Hardware zählt nicht in Bytes, sondern sie ist in Bits implementiert. Wenn man ein bestimmtes Bit nicht braucht, wird es eben gar nicht erst realisiert.
Jörg Wunsch wrote:
> Das erklärt das Symptom natürlich. ...
Ist aber auch nur eine Vermutung, die zumindest die "2" da erklären
würde...
Aber die 2 schreibt er da schon bewusst rein. Ich habe vorher mal den ganzen Speicher mit Nullen gefüllt, aber sobald der entsprechende Breakpoint erreicht ist, klatscht er die 2 zusammen mit der Adresse da rein :-(
Seltsam isses schon. Aber wie gesagt, eine Bedeutung dürfte dem Bit nicht zukommen. Zumindest nicht in Hinblick auf den Programmzähler/die Rücksprungadresse...
Josch wrote:
> Aber die 2 schreibt er da schon bewusst rein.
Ja, sehe ich jetzt auch, habe mir auch mal einen ATmega16 rausgekramt.
Ich vermute mal, dass das eine Optimierung des Hardwarecompilers ist.
In der Hardwarebeschreibung gibt es außer 0 und 1 noch diverse
andere mögliche Zustände, u. a. kann man da auch sagen, dass einen
ein bestimmtes Bit gar nicht interessiert. Bei der Synthese des
Gatternetzwerkes steht es dann dem Compiler frei, dafür einen
beliebigen Bitwert einzutragen, was auch immer das kleinere Gesamtnetz
ergibt.
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.