Hallo Ich programmiere gerade einen tiny45 und habe ein problem mit RJMP. Das ganze wird ein Bootloader der bei adresse h0000 sitzt. Der Bootloader prüft zu beginn, ob ein Update ansteht, wenn nicht soll er zu Adresse h580 springen (Anwenderprogramm). Ist noch kein Anwenderprogramm geladen ist bei der besagten Adresse nichts. Der AVR sollte dann doch einfach bis zum ende des Speichers durchrasseln und danach nichts mehr tun, oder ? Mein tiny macht jedoch permanent ein Reset, und startet immer wieder neu. Wiso dass ?? Sollte der doch nicht, oder ? Ich weis nicht ob der tiny überhaupt zu adresse h580 springt, oder irgendwo anders hin geht ??
Michael L. schrieb: > ist bei der besagten Adresse nichts. Der AVR sollte dann doch einfach > bis zum ende des Speichers durchrasseln und danach nichts mehr tun, Wie kommst du auf diese Idee? Er wird eher wieder vorne anfangen.
> Der AVR sollte dann doch einfach bis zum ende des Speichers durchrasseln Sofern lauter nops (oder undefinierte Kommandos) drinstehen, ja. > und danach nichts mehr tun ..und wieder von vorne anfangen. HTH
Hallo, diese Verhalten ist nomal, wenn der Speicher leer ist (0xFF) läuft er hoch bis zum Ende und bei erreichen der maximalen Adresse des PC wird dieser wieder auf 0x0000 gesetzt. Damit geht dein Programm wieder von vorn los. Prüfe doch im Bootloader ob an Addr 0x580 0xFF steht oder nicht, dann kannst du selbst eine Endlosschleife einbauen. Sascha
alles klar ! jetzt funktioniert der sprung zu h580. Ich habe nun ein endlosprogramm geladen, dass immer "H" alle 500ms sendet. jedoch kommt ein totaler mist beim Computer an ?! Wenn ich das Programm per USBASP wieder auslese wird alles richtig im speicher abgelegt. Lade ich das programm ohne Bootloader funktionierts. Darf ich das Anwenderprogramm im tiny nicht einfach auf eine andere Adresse legen ?
Michael L. schrieb: > Darf ich das Anwenderprogramm im tiny nicht einfach auf eine andere > Adresse legen ? Das hängt vom Programm ab. Man KANN Programme schreiben, die garantiert auf jeder Adresse lauffähig sind. Aber wenn man das nicht gezielt macht, ist die Chance relativ groß, daß ein Programm nur auf der Adresse lauffähig ist, für die es assembliert bzw. gelinkt wurde.
@Michael Ein weiteres Problem sind die Interruptvektoren, da die ab Adresse 0x0000 liegen - und damit in deinem Bootloader - sind die im Programm in dem Fall überhaupt nicht mehr verwendbar. Ausser! -> du baust im Bootloader an den Adressen der Interruptvektoren schon Sprünge ein um die Aufrufe in den Speicherbereich deines späteren Programms umzuleiten. In welcher Sprache schreibst du überhaupt dein Programm? Sascha
den Bootloader programmiere ich mit Bascom jedoch relativ viel in ASM. Das Problem mit den Interruptvektoren habe ich in der zwischenzeit auch erkannt. Letztendlich soll bei einem Reset immer zuerst der Bootloader gestartet werden und danach das Anwenderprogramm. Sascha Weber schrieb: > Ausser! -> du baust im > Bootloader an den Adressen der Interruptvektoren schon Sprünge ein um > die Aufrufe in den Speicherbereich deines späteren Programms umzuleiten. Wie genau meinst du das ? Kannst du eine schematische skizze machen ?? Wo genau müssen die Sprünge sein ?
Hallo, die ISR Vectoren liegen beim 45 von Addr: 0x0000 bis 0x000e Im Bootloader machst du folgendes: 0x0000 rjmp Startbootloader 0x0001 rjmp 0x581 0x0002 rjmp 0x582 ... 0x000e rjmp 0x58e ---- Bootloader ... ---- App... 0x0580 rjmp Appstart 0x0581 reti /Int0 0x0582 reti /PCINT0 ... 0x058e reti /USI_OVF ---- Du legst also am Anfang deiner Application eine Kopie der ISR Vectoren an. Wenn du die App in der Hochsprache schreibst, weiß ich allerdings jetzt nicht wie man der beibringt das die ISR-Adressen wo anders liegen. Sascha
OK Super, alles klar ! mit dem befehl $noinit legt Bascom keinen Interruptvektor zu beginn des Programms an, soweit gut. Jedoch weis ich nicht wie ich meinen eigenen Interruptvektor schreibe. Wenn ich zu beginn des Programms einen RJMP befehl einsetzte, taucht der befehl im Kompilierten Programm erst irgendwo später auf (ab h20, oder sowas). Wie muss ich dass nun anstellen, damit mein RJMP befehl direkt als erstes kompiliert wird ?
Michael L. schrieb: > Wie muss ich dass nun anstellen, damit mein RJMP befehl direkt als > erstes kompiliert wird ? Da ich nur in ASM programmiere kann ich dir da jetzt nichtweiterhelfen. Sascha
Michael L. schrieb: > Bootloader der bei adresse h0000 sitzt. Wenn du deinen Bootloader ans Ende des Speichers, FLASHEND - BOOTSIZE, setzt und in diesem keine Interrupts verwendest, brauchst du nur noch den Resetvektor verbiegen und deine anderen Probleme, die sich daraus ergeben, dass der Bootloader bei 0 anfängt, lösen sich in Wohlgefallen auf. mfg.
Michael L. schrieb: > Interruptvektor schreibe. Wenn ich zu beginn des Programms einen RJMP > befehl einsetzte, taucht der befehl im Kompilierten Programm erst > irgendwo später auf (ab h20, oder sowas). Und was steht von 0x00 - 0x20 ? Wenn Bascom dort mit seiner Stackinitialisierung rumfummelt, wirst du kaum was tun konnen. Wenn da allerding 0xFF steht, kannst du folgendes probieren (am Start deines BASIC Programms): $Asm .org 0x00 rjmp MyBootLoader ;* Oder rjmp 0x580 $End Asm Michael L. schrieb: > Wie muss ich dass nun anstellen, damit mein RJMP befehl direkt als > erstes kompiliert wird ? Ich glaube, du denkst da in die falsche Richtung. Bootloader wird nur einmal programmiert, alle anderen Programme werden über ihn und nicht direkt programmiert. Bei deinem Bootloader wurde ich das folgendermassen machen: '* Bascom init ... '* Dein Programm, die Startadresse ist egal $Asm rjmp MyBootLoader $End Asm ... ... $Asm .org Flashsize - BootLoaderSize - 2 OldReset: rjmp MyBootLoader ;* z.Zt. ist das BootLoader Adresse MyBootLoader: ... ... $End Asm Wenn du neue Programme auflädst, werden die ganz normal vom Bootloader ins Flash geschrieben, zum Schluss nimmt der Bootloader die Adresse 0x00, schreibt deren Inhalt ins Flash, auf Adresse OldReset. Auf Adresse 0x00 schreibt der seine eigene Adresse. So brauchst du keine Arithmetik mit Adressen - jedes neue Programm wird normal auf Adresse 0x00 compiliert und startet auch ganz normal von 0x00. Bootloader wartet am Start ein paar Sekunden auf Zeichen, wenn nichts kommt, springt der zur Adresse OldReset. Beim ersten Mal steht da die Adresse vom Bootloader, also wird der ewig auf ein Zeichen warten. Wenn du aber irgendein Programm auflädst, wird da die Adresse von neuen Programm stehen und somit springt der ( nach paar Sekunden ) ins neue Programm. Thomas Eckmann schrieb: > und deine anderen Probleme, die sich daraus ergeben, dass der > Bootloader bei 0 anfängt, lösen sich in Wohlgefallen auf. Ganz genau. EDIT: Natürlich rjmp aus der Adresse 0x00 vorher umrechnen.
Marc Vesely schrieb: > Ich glaube, du denkst da in die falsche Richtung. > Bootloader wird nur einmal programmiert, alle anderen Programme > werden über ihn und nicht direkt programmiert. Ist mir schon klar.. Marc Vesely schrieb: > $Asm > .org 0x00 > rjmp MyBootLoader ;* Oder rjmp 0x580 > $End Asm Funktioniert mit Bascom nicht. Wenn ich das ganze so mache: Bootloader ans ende des Flashes. Das Anwenderprogramm ganz normal auf h00, Wenn das Anwenderprogramm per Bootloader geladen wird, dann direkt den ersten RJMP-Befehl mit der Adresse des Bootloaders ersetzten. Wenn ich vom Bootloader zum Anwenderprogramm zurück will, dann einfach die ersetzte Adresse anspringen. Oder ??
Michael L. schrieb: > Wenn ich das ganze so mache: Bootloader ans ende des Flashes. Das > Anwenderprogramm ganz normal auf h00, Wenn das Anwenderprogramm per > Bootloader geladen wird, dann direkt den ersten RJMP-Befehl mit der > Adresse des Bootloaders ersetzten. Wenn ich vom Bootloader zum > Anwenderprogramm zurück will, dann einfach die ersetzte Adresse > anspringen. Oder ?? Nur wenn alle Anwendungsprogramme dort wirklich einen Sprungbefehl stehen haben. Das ist keine zwingende Notwendigkeit. Außerdem mußt du berücksichtigen, daß bei den größeren AVRs da auch andere Sprungbefehle als rjmp stehen können. Und bei rjmp muß du beachten, daß die Zieladresse relativ ist, du kannst also den Sprungbefehl nicht unverändert benutzen, sondern mußt erstmal die absolute Zieladresse daraus berechnen.
Michael L. schrieb: > Adresse des Bootloaders ersetzten. Wenn ich vom Bootloader zum > Anwenderprogramm zurück will, dann einfach die ersetzte Adresse > anspringen. Oder ?? Nein, mit einfachen kopieren geht das nicht. Wenn es 'ne größere MEGA wäre mit mehr als 8KB Flash, dann ja, aber hier handelt es sich um relative Adressen. Was dort steht ist der Offset von der Adresse des Befehls zur SprungAdresse - 1. In deinem Beispiel steht 'C0 0E', also springt das Program auf Adresse 0E + 1 = 0F. Da es sich um Wordadressen handelt, ist das alles mal zwei, ergibt Adresse 0x1E - da springt dein Programm beim Start oder Reset. Es war eine nicht besonders kluge Entscheidung von Atmel mal mit Byte, mal mit Word zu hantieren, aber es ist so. Auf jeden Fall must du zuerst ausrechnen wo das alte Programm springt, dann den Offset vom 'OldReset' zur alten Adresse und dann diesen Offset in 'OldReset' eintragen. Natürlich vorher das LowByte mit 0x0F AND-en and nachher mit 0xC0 OR-en. Klingt komplizierter als es in Wirklichkeit ist - es sind kaum mehr als 10 Zeilen in Assembler.
c-hater schrieb: > Nur wenn alle Anwendungsprogramme dort wirklich einen Sprungbefehl > stehen haben. Das ist keine zwingende Notwendigkeit. Außerdem mußt du Stimmt, aber er programmiert in Bascom und da wird es schon so sein. Und warum uberhaupt jemand in senem Programm auf InterruptTable verzichten sollte, war mir nie klar. c-hater schrieb: > Außerdem mußt du > berücksichtigen, daß bei den größeren AVRs da auch andere Sprungbefehle > als rjmp stehen können. Er will das aber für Tiny45 schreiben, wie sollen da größere AVRs reinkommen ?
Marc Vesely schrieb: > Er will das aber für Tiny45 schreiben, wie sollen da größere AVRs > reinkommen ? JETZT will er es für den Tiny45 schreiben. Aber es könnte ja gut sein, daß der Bootloader irgendwann auch mal für andere Typen verwendet werden soll. Dann wäre es gut, wenn er über diese Information verfügt, auch wenn er sie JETZT vielleicht noch nicht unbedingt braucht. Wenn er auch nur halbwegs clever ist, sieht er aber von vornherein diese Fallunterscheidung vor.
c-hater schrieb: > Wenn er auch nur halbwegs clever ist, sieht er aber von vornherein diese > Fallunterscheidung vor. Ja.
c-hater schrieb: > JETZT will er es für den Tiny45 schreiben. Aber es könnte ja gut sein, > daß der Bootloader irgendwann auch mal für andere Typen verwendet werden > soll. Dann wäre es gut, wenn er über diese Information verfügt, auch > wenn er sie JETZT vielleicht noch nicht unbedingt braucht. So ist es. Eins nach dem andern, zuerst soll das ganze zu Testzwecken auf einem tiny45 laufen, danach auch auf einem Mega328. Das Ziel ist, dass der Bootloader auf jedem AVR läuft. Der Bootloader ansich funktioniert einwandfrei, man kann das Eeprom beschreiben, den Flash beschreiben und löschen, als auch die Fuses sowie Kalibrierdaten auslesen. Auch die Computersoftware ist bereits fertig, diese ist für MAC und Windows verfügbar (siehe Bild im Anhang). Das Problem ist momentan nur der Bootloaderaufruf nach einem Reset. Ich werde dies mit dem RJMP usw. testen. Noch was: beim Mega328 ist der erste Befehl wie bereits erwähnt, kein RJMP, sondern wenn ich es richtig verstehe, ein JMP, und es wird zur gleichen Adresse gesprungen wie beim tiny45. Stimmt das so ? Beim RJMP-befehl ist immer relative Adresse + 1, beim JMP absolute Adresse.
Michael L. schrieb: > Noch was: beim Mega328 ist der erste Befehl wie bereits erwähnt, kein > RJMP, sondern wenn ich es richtig verstehe, ein JMP, Controller bis 8K Flash, also alle Attinys und die kleineren Megas, benutzen RJMP. Die Typen mit >8K JMP. > und es wird zur > gleichen Adresse gesprungen wie beim tiny45. Stimmt das so ? Nein. Der Sprung erfolgt in aller Regel auf die erste Speicherstelle hinter der Vektortabelle. Diese ist aber nicht bei allen Controllern gleich lang. Warum willst du bei den Atmegas den Bootloadersupport nicht benutzen? Bis auf Atmega48 haben die das alle. Damit ersparst du dir jegliches Rumgehampel mit verbogenen Vektoren und die Ermittlung von Sprungadressen. Der Bootloader startet automatisch und der Sprung in die Anwendung erfolgt immer auf Adresse 0. mfg.
Michael L. schrieb: > Noch was: beim Mega328 ist der erste Befehl wie bereits erwähnt, kein > RJMP, sondern wenn ich es richtig verstehe, ein JMP, und es wird zur > gleichen Adresse gesprungen wie beim tiny45. Stimmt das so ? Das mit JMP stimmt, mit der Adresse nicht. Thomas Eckmann schrieb: > Der Sprung erfolgt in aller Regel auf die erste Speicherstelle hinter > der Vektortabelle. Diese ist aber nicht bei allen Controllern gleich > lang. Und genau da springt dein Programm hin, Adresse ist 0x68. Und was du da eingekreist hast, ist nur der halbe Befehl. Versuche erst mal BL für Tiny45 fertig zu kriegen.
der alte Hanns schrieb: > Wie kommt man auf die 0x68 ? Das ist für den Atmega 328. 0x94 0C 00 34 ist ein jmp auf die Wordadresse 0x34. Also Byteadresse 0x68. mfg.
Thomas Eckmann schrieb: > Warum willst du bei den Atmegas den Bootloadersupport nicht benutzen? Doch bei den Megas werde ich das bestimmt so machen. Aber erst bin ich noch bei dem tiny. Wie gesagt, soll der Bootloader möglichst auf jedem AVR lauffähig sein, der Bootloader kann dann je nach AVR typ, und gewünschten Optionen, individuell konfiguriert werden. Marc Vesely schrieb: > Und was du da > eingekreist hast, ist nur der halbe Befehl. Aha, wieder was dazu gelernt.
so ich melde mich nun wieder.. Habe das ganze mit dem RJMP auf dem tiny45 geteste, jedoch funktioniert noch nicht alles. Der Bootloader sitzt bei word adresse H580. Der Bootloader ersetzt den ersten Befehl des Anwenderprogramms durch die Adresse des Bootloaders. Bei einem Reset des AVR wird auch sauber zum Bootloader gesprungen. Möchte ich vom Bootloader wieder zurück zum Anwenderprogramm, springe ich zur originalen word-adresse h0E des Anwenderprogramms (rote Markierung Bootloader.png). Das Problem: das Anwenderprogramm startet gar nicht, es wird sofort wieder der Bootloader aufgerufen. was genau ist da das Problem ??
Michael L. schrieb: > Der Bootloader sitzt bei word adresse H580. Der Bootloader ersetzt den > ersten Befehl des Anwenderprogramms durch die Adresse des Bootloaders. > Bei einem Reset des AVR wird auch sauber zum Bootloader gesprungen. > Möchte ich vom Bootloader wieder zurück zum Anwenderprogramm, springe > ich zur originalen word-adresse h0E des Anwenderprogramms (rote > Markierung Bootloader.png). Das Problem: das Anwenderprogramm startet > gar nicht, es wird sofort wieder der Bootloader aufgerufen. was genau > ist da das Problem ?? Du hast offensichtlich das Problem, nichtmal mit einem Taschenrechner umgehen zu können. ;o) Die Originalsoftware hat die Instruktion $c00e decodiert: rjmp PC+$e Da an der Stelle der Instruktion der PC=0 ist, springt die Instruktion also effektiv auf die absolute Wordadresse $0e. Soweit hast du das völlig richtig erkannt. So, der rjmp in deinem Bootloader steht auf Byteadresse $b94, also auf Wordadresse $5ca. Um zu der absoluten Wordadresse $e zu springen, müßte er also ein Displacement von $00e -$5ca ----- $a44 im Opcode enthalten, der gesamte Opcode müßte also $ca44 lauten. Bei dir steht dort allerdings $ca43, was also definitiv schonmal falsch sein muss. Spannender ist jetzt eigentlich, was da dann wirklich passiert: $5ca -$a43 ----- $d Er springt also zu Adresse $d im Anwendungscode. Bei einem für Tiny45 compilierten Programm also in den USI_STARTaddr-Interruptvector. Die konkrete Anwendung nutzt diesen Interrupt offensichtlich nicht, denn auf diesem Vector steht dort nur ein schlichtes "reti". Was genau weiter passiert, hängt also dann davon ab, was auf [SP] und [SP]+1 im SRAM steht. Das geben deine Screenshots leider nicht her. Aber, wenn du wieder im Bootloader landest, bist du noch gut bei der Sache weggekommen. In ernsthaften Anwendungen können bei sowas auch mal Millionenwerte abrauchen. Und dabei ist's nur ein Bug der allseits beliebten "off by one"-Klasse...
Du gibst beim RJMP im Bootloader einen positiven Versatz an, springst also nach vorn in's Nirgendwo, mit anschließendem Neustart. https://anibit.com/webtools/small/rjmp_calculator/ Auch überspringst Du den ersten Befehl im Bootloader, da der Versatz um 1 Word zuviel ist. Lies Dir dazu das AVR Instruction Set zum RJMP durch, ein C000 springt z.B. auf PC +1
c-hater schrieb: > Und dabei ist's nur ein Bug der allseits beliebten "off by > one"-Klasse... Häha, und ich selber auch gleich nochmal. Wer im Glashaus sitzt... Tatsachlich springt die Anwendung auf $f. Der Fehler im von dir errechneten Displacement ist aber nach wie vor 1 Word, du springst also $e statt $0f an und damit USI_OVFaddr. Auch hier steht ein "reti", der Rest bleibt deshalb wie beschrieben.
MWS schrieb: > Du gibst beim RJMP im Bootloader einen positiven Versatz an, > springst > also nach vorn in's Nirgendwo, mit anschließendem Neustart. Korrektur, hatte 'nen Zahlendreher bei der Eingabe, Sprung geht zurück, aber um 1 falsch.
Michael L. schrieb: > Markierung Bootloader.png). Das Problem: das Anwenderprogramm startet > gar nicht, es wird sofort wieder der Bootloader aufgerufen. was genau > ist da das Problem ?? Deine Umrechnung. Du springst weder zur Adresse 0x0F, noch 'nach vorn in's Nirgendwo', sondern wahrscheinlich irgendwo hinter deinem UserProg, mitten in FF's, also rutscht der Bootloader lustig durch die NOPs, bis er wieder bei seinem start angelangt ist. Nach vorn ins Nirgendwo geht nicht, weil der PC bei Überlauf wieder von vorne anfangt. Probier mal mit C4-79 ( ohne etwas am userprog zu ändern ). Nicht ausprobiert, nicht ausgerechnet, nur so aus dem Kopf, also mache ich damit vielleicht einen noch größeren Fehler als du.
Marc Vesely schrieb: > In deinem Beispiel steht 'C0 0E', also springt das Program auf > Adresse 0E + 1 = 0F. Da es sich um Wordadressen handelt, ist das > alles mal zwei, ergibt Adresse 0x1E - da springt dein Programm > beim Start oder Reset. Jetzt funktionierts ! Unter Bascom habe ich den Befehl Goto &h1E, statt &h0E genommen. Ist irgenwie verwirrend mit den Adressen, einmal word, dann doch wieder byte... Compiliert ergibt sich &hCA53. Ich hoffe das ist so richtig, und nicht einfach nur zufall, dass das Anwenderprogramm läuft ?! MWS schrieb: > Auch überspringst Du den ersten Befehl im Bootloader, da der Versatz um > 1 Word zuviel ist. OK, also muss ich den ersten Befehl mit &hC57F ersetzen ?
Michael L. schrieb: > OK, also muss ich den ersten Befehl mit &hC57F ersetzen ? Ja, hast Du nicht den verlinkten Rechner ausprobiert? Für solche (und andere) Sachen würde ich ReAVR ja-Tools empfehlen, da werden Sprünge in Labels aufgelöst. Auch nützlich ist unter Bascom ein obj-File erstellen lassen und dieses dann z.B. in AVR Studio 4 laden. Dann lässt sich der Code simulieren und in der Assembleransicht verfolgen, was da vor sich geht.
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.