Hallo zusammen Ich habe einen eigenen Bootloader programmiert, der soweit auf dem tiny45 einwandfrei funktioniert. Nun habe ich diesen für einen ATmega328p anpassen wollen, jedoch kann ich mit dem Bootloader den Flash nicht beschreiben. Ich kann machen was ich will, es geht einfach nicht. Ist im AVR Irgenwie ein Schreibschutz aktiviert ?!? Anbei die Fusebit Einstellungen. Was hat es genau mit den RWW bits im SPMCSR Register auf sich ? Blicke da irgendwie noch nicht ganz durch.
Michael L. schrieb: > Was hat es genau mit den RWW bits im SPMCSR Register auf sich ? Blicke > da irgendwie noch nicht ganz durch. Auf welcher Adresse befindet sich dein Bootloader genau ?
Michael L. schrieb: > Bootloader startet bei Adresse 0x3C00 Nöö, dein Bootloader startet überhaupt nicht. Bootloader size ist 1024 Byt, also sollte der auf 3E00 starten (Word Adress). Und selbst wenn der starten sollte, geht SPM in die Hose, eben wegen RWW und NRWW.
:
Bearbeitet durch User
Marc Vesely schrieb: > Bootloader size ist 1024 Byt gemäss fuses sind es doch 1024 word ? also stimmt 0x3C00 doch ? Marc Vesely schrieb: > Nöö, dein Bootloader startet überhaupt nicht. Doch der Bootloader selber funktioniert, er kommuniziert jedefalls mit dem Computer, nur wird der Flash nicht beschriben...
Michael L. schrieb: > gemäss fuses sind es doch 1024 word ? also stimmt 0x3C00 doch ? Ja, sorry. Bleibt nur noch die Pagesize und evtl. IVSEL bit. Ist IVSEL gesetzt ? Wenn ja, befindet sich deine Int-Table laut High-Fuse im Bootsector. Wenn nein, poste mal deinen Code zum Page beschreiben.
IVSEL sollte nicht gesetzt sein, jedenfalls habe ich es nicht gesetzt. Eine int-table habe ich im Bootloader nicht. Anbei der Code (ist in Bascom).
Michael L. schrieb: > Anbei der Code (ist in Bascom). Wenn das alles ist: Ich sehe nicht, dass du hier irgendwo den Status abfragst ? ( SELFPRGEN in SPMCSR ) Bei MEGA muss gewartet werden, bis SPM fertig ist ! Probiere mal so: .equ c_StoreData = 0x01 .equ c_PageErase = 0x03 .equ c_PageWrite = 0x05 .equ c_RWW_Ena = 0x11 EraseFlashPage: ldi r17, c_PageErase out SPMCSR, r17 spm ;***** Warte fur SPM (ATmega)! ***** SPMwait: in r17, SPMCSR sbrc r17, SELFPRGEN ; warte auf vorh. SPMEN rjmp SPMwait ldi r17, c_RWW_Ena ; set RWWSRE und SPMEN out SPMCSR, r17 spm ret Dasselbe gilt für schreiben.
funktioniert auch nicht. braucht es 2mal SPM ? Nach dem RWWSRE nochmal SPM ?
Michael L. schrieb: > funktioniert auch nicht. braucht es 2mal SPM ? Nach dem RWWSRE nochmal > SPM ? Ja. Also ich erase zuerst den ganzen Flash, von oben nach unten - Bootstart - 1 bis 0x0000. Dann write ich die Pages von 0x0000 bis Programmende. Allerdings nicht so zerstückelt wie du, sondern zuerst Page Buffer ganz beschreiben, danach Page Write und warten auf SELFPRGEN. Funktioniert ohne Probleme. Und noch etwas: Versuche mal, den Konstanten sinnvolle Namen zu geben: ldi r17, c_PageErase ist lesbarer als: ldi r17, &B0000011 erstens kann man sich bei so vielen Nullen leicht verzählen und zweitens sagt mir ( und dir, nach 2 Wochen ) &B00000011 gar nichts. Kleines c davor bezeichnet const, ist viel leichter so. Nicht jeder, der helfen will, hat auch Lust (und Zeit) Datenbücher zu wälzen um die Bedeutung von &B00000011 zu finden.
So der Bootloader ansich würde jetzt funktionieren. Das userprog wird nun korrekt in den Flash geschrieben. Jedoch habe ich noch ein anderes Problem: Nach dem ersten update, kann ich denn Bootloader nicht mehr ansprechen und das Userprog läuft auch nicht. Gemäss Fuse Einstellungen soll der AVR nach dem Reset zum Bootloader springen, funktioniert jedoch auch nicht richtig, er bleibt dann irgendwo hängen... Mit Fuse Einstellung, das der RESET Vektor 0x0000 aufgerufen wird nach dem Reset, läuft wenigstens das Userprog. Jedoch kann ich so den Bootloader nicht automatisch starten.
Michael L. schrieb: > und das Userprog läuft auch nicht. Gemäss Fuse Einstellungen soll der > AVR nach dem Reset zum Bootloader springen, funktioniert jedoch auch > nicht richtig, er bleibt dann irgendwo hängen... Stromzuführung abschalten, wieder einschalten, dasselbe ? > Mit Fuse Einstellung, das der RESET Vektor 0x0000 aufgerufen wird nach > dem Reset, läuft wenigstens das Userprog. Jedoch kann ich so den Láß die Vektoren im Bootloader, probiere es mit ein- und ausschalten. Wenn es trotzdem nicht funktioniert, mit ISP-Programmer Bootloader flashen, FLASH auslesen und als Datei-1 speichern, mittels Bootloader Userprog laden, wieder mit ISP-Programmer FLASH auslesen und als Datei-2 speichern. Beide Dateien vergleichen.
:
Bearbeitet durch User
Marc Vesely schrieb: > Beide Dateien vergleichen Beide Dateien sind identisch. An dem liegts nicht. Folgendes habe ich versucht: - Fuse Einstellung auf Reset-vector 0x0000 - Bootloader geflasht - 1.mal starten, der AVR beginnt bei 0x0000, läuft durch bis er beim Bootloader ankommt -> Bootloader startet - per Bootloader das userprog geladen - nach neuem Reset läuft direkt das userprog, soweit OK, nur kann ich natürlich den Bootloader nicht mehr ansprechen Mache ich alles gleich, nur mit Fuse Einstellung Bootvector, Funktioniert der Bootloader nur das 1.mal, und das userprog läuft auch nicht. Folgendes sollte nach dem Reset passieren: - Reset - Start bei Bootloader - Bootloader wartet auf ein Zeichen, kommt nichts, gehe zu 0x0000
Michael L. schrieb: > Mache ich alles gleich, nur mit Fuse Einstellung Bootvector, Marc Vesely schrieb: > Ist IVSEL gesetzt ? Etwas anderes fällt mir gerade nicht ein.
anbei mal der Bootloader Code, vielleicht hilft es. Im Bootloader sind die Interrupts ausgeschaltet. Zur Fehlersuche, sollte der Bootloader als erstes "Boot" als text senden, somit sehe ich ob er gestartet ist. Dies funktioniert auch, solange noch kein userprog geladen ist. Ist ein userprog geladen, kommt kein "Boot", also startet der Bootloader auch nicht. Das userprog läuft jedoch auch nicht, was genau macht denn der AVR, wohin springt er ?? Habe nochmals den Flash per ISP ausgelesen und kontrolliert, das userprog wird korrekt geschrieben, und der Bootloader wird auch nicht überschrieben. Mit dem IVSEL-bit habe ich auch einige versuche gemacht, jedoch ohne unterschied.
solange ich keine interrupts im Bootloader habe und ausgeschaltet sind, ist doch das IVSEL-bit nicht zu beachten ?
Michael L. schrieb: > solange ich keine interrupts im Bootloader habe und ausgeschaltet sind, > ist doch das IVSEL-bit nicht zu beachten ? Wie ist deine Boot Reset Fuse programmiert ? Die muss ins Bootloader zeigen, also programmiert sein (0).
:
Bearbeitet durch User
langsam aber sicher komme ich dem Fehler auf die Spur, das Problem ist, dass ich im Bootloader die Hardware UART verwende. Obwohl die interrupts ausgeschaltet sind, werden trotzdem zur kommunikation irgendwelche status register des UARTs abgefragt. Solange kein userprog geladen ist funktioniert auch alles, mit geladenem userprog funktioniert die Hardware UART nicht mehr, wiso auch immer.... Weiter ist die folge, das der AVR dann irgendwo hängen bleibt, dadurch funktioniert weder der Bootloader, noch das userprog. Habe nun im Bootloader eine SW UART genommen, nun funktioniert nach dem update wenigstens das userprog. Im Bootloader muss ich jedoch noch einen anderen fehler suchen...
Michael L. schrieb: > Habe nun im Bootloader eine SW UART genommen, nun funktioniert nach dem > update wenigstens das userprog. Im Bootloader muss ich jedoch noch einen > anderen fehler suchen... Strikt im Bootloader bleiben, keine, wie auch immer geschriebene Routinen ausserhalb benutzen. P.S. Atmel sagt: In ATmega88A/88PA, ATmega168A/168PA and ATmega328/328P, the Reset Vector is affected by the BOOTRST fuse, and the Interrupt Vector start address is affected by the IVSEL bit in MCUCR. P.P.S. Natürlich darfst du UCSR0A abfragen und UDR0 benutzen, nur eben in Bootloader bleiben.
:
Bearbeitet durch User
Marc Vesely schrieb: > Strikt im Bootloader bleiben, keine, wie auch immer geschriebene > Routinen ausserhalb benutzen. ist mir schon klar, mache ich auch nicht. Folgendes funktioniert: - Fuse auf BOOT Reset eingestellt - Bootloader startet, und der AVR kann geupdatet werden - Neues userprog wird nach update gestartet, und läuft auch nach einem Reset - sowit alles gut Nun ein weiteres Problem: - Der Bootloder startet zwar nach einem Reset, das Timeout wird runtergezählt, wenn dann nichts per UART kommt, springt er zum userprog, soweit alles richtig - Kommt jedoch per UART ein &h07, sollte der Bootloader sich mit dem Zeichen "@" melden, stattdessen sendet er etwas über 1000bytes, genaugenommen kommen die restlichen Bytes vom Flash und zwei vom Anfang des Flashes (FF FF FF... FF 94 0C). Komische Sache.. liegt das etwa an BASCOM ?
Michael L. schrieb: > - Kommt jedoch per UART ein &h07, sollte der Bootloader sich mit dem > Zeichen "@" melden, stattdessen sendet er etwas über 1000bytes, > genaugenommen kommen die restlichen Bytes vom Flash und zwei vom Anfang > des Flashes (FF FF FF... FF 94 0C). > > Komische Sache.. liegt das etwa an BASCOM ? Glaube ich nicht. Ist Zeichen "@" definiert, und wenn ja, wo ? Ich glaube, Bascom sieht das als ein String und Strings müssen Nullterminiert sein, also sendet dein Bootloader alles bis 0x00...
:
Bearbeitet durch User
dem Fehler auf der Spur !! Also der Bootloader wird nach dem ersten userprog-update am ende bei Adresse 0x7B80 mit 0xFF überschrieben. Dies erklärt auch den Fehler, den das Bereit-Zeichen "@" ist nähmlich in dem Bereich des Flashes gespeichert. Was mich jedoch stutzig macht ist, dass ich das Fusebit65 = &b10 (SPM im Bootsector gespert) aktiviere, also sozusagen den Schreibschutz, es nach dem flashen des Bootloaders sofort wieder auf &b11 steht(kein schreibschutz). Wiso denn das ? Werde nachmals kontrollieren, ob ein Fehler im Bootloader-code besteht, und ob er sich dadurch wirklich selber überschreiben kann.
So der Bootloader funktioniert nun, und wird auch nicht mehr überschrieben. Einen Fehler im Bootloader selber habe ich keinen feststellen können, habe stattdessen einfach den Schreibschutz für den Bootsector gesetzt. Die Lockbits kann ich nicht per ISP setzten, diese werden bei erneutem flashen sofort wieder zurückgesetz. Die Lockbits kann ich nur im Bootloader setzten. Jetzt trotzdem noch was: Lade ich per Bootloader ein userprog, kann ich beim zweiten mal die bereits beschriebenen pages (userprog) nicht mehr überschreiben, wiso denn das ?? Habe keine Ahnung was sonst noch für ein Schreibschutz aktiviert sein könnte. Im Datenblatt finde ich auch nichts, auf jedenfall weis ich nicht wie sich das nennen sollte. Hat jemand eine Idee ? Anbei die gesetzten Lockbits.
Michael L. schrieb: > Die Lockbits kann ich nicht per ISP setzten, diese werden bei erneutem > flashen sofort wieder zurückgesetz. das ist ja auch richtig so, vor dem flaschen wir ein chip-erase gemacht der loescht auch die Lockbits, nach dem Flashen kannste sie aber wieder Proggen, natuerlich ohne chip-erase sonst ist dein Prg wieder wech vlG Charly ps. was haste fuer ein Programmer ?
Hast Du beachtet, dass eine page erst gelöscht werden muss, bevor sie programmiert werden kann? Hintergrund: programmieren heißt hier: ein Bit wird auf 0 gesetzt, der "Urzustand" = unprogrammierte Zustand ist: 1 (umgekehrte Logik!) und muss durch "Page löschen" erzeugt werden. Deshalb steht im leeren Speicher immer 0xFF (hoffe, das ist einigermaßen verständlich)
Dieter M. schrieb: > Hast Du beachtet, dass eine page erst gelöscht werden muss, bevor sie > programmiert werden kann? Ja, ich gehe so vor: - Page löschen - Daten in Puffer laden - Puffer in Flash schreiben sollte doch eigentlich funktionieren ? Auch eine bereits beschriebene Page mit &hFF überschreiben funktioniert nicht.
Michael L. schrieb: > Ja, ich gehe so vor: > - Page löschen > - Daten in Puffer laden > - Puffer in Flash schreiben > > sollte doch eigentlich funktionieren ? Wie wäre es mit Programm selbst, anstatt mit Beschreibung ?
Michael L. schrieb: > anbei der Programm Code Ack. Nimm es mir nicht übel, aber so was ist Spaghetti code. Ich kann mich da wirklich nicht durchschlängeln... Was ich gesehen habe ist folgendes:
1 | Clear_buffer:
|
2 | For H = 1 To 16 |
3 | Buffer(buffer_pointer) = &HFF |
4 | Incr Buffer_pointer |
5 | Next
|
6 | Return
|
Ob du diese Routine allerdings 8 mal hintereinander aufrufst, kann ich nicht sagen. Die ganzen '#if' machen diesen Programm zu einem Alptraum. Sowas kommt erst am Ende, wenn alles funktioniert. Also keine Befehle, keine Abfragen, keine #if-s und sonstiges. Sende eine Page, programmiere die, hole die nächste und so 5-10 Pages hintereinander. Wenn es funktioniert, Adresse oder PageNr. dazugeben, wenn es klappt, eine Funktion nach der anderen dazugeben... '#if', wenn überhaupt, ganz am Ende.
:
Bearbeitet durch User
Wenn du auf mich hören willst: Die ganzen defines, const und anderes in ein Headerfile packen. Soviel ich weiss, hat Bascom Select-Case, also: Main loop zum Abfragen - vorerst nur 2 Commands, Read und Write. Do Inputbin #1 , RcvdChar Select Case RcvdChar Case ASC("R") : Gosub ReadPage Case ASC("W") : Gosub WritePage Case ASC("Q") : Goto Reset Case Else : Print #1 , "?" End Select Loop Oder so ähnlich, ich kenne Bascom nicht. Zwei Subs, ReadPage und WritePage, Do_SPM getrennt wie bisher, Teile vom Programm, die zusamengehören, auch zusammen lassen, nicht durch leere Zeilen trennen, sowas wie Überschrift für zusätzliche SUBs oder Programmblocks kann auch nützlich sein: '****************************************** '** Buffer mit FFs füllen ** '** Wird 8x aus zz aufgerufen ** '** buffer_pointer wird in yy gesetzt ** '****************************************** Wenn du eine Routine aufrufst, kann ein kurzes Kommentar was diese Routine machen soll und was die Argumente bedeuten, sicher nicht schaden. Wenn du dann nach 2 Monaten deinen Programm ändern willst, wird es viel leichter sein. Auch werden sich hier im Forum wahrscheinlich etwas mehr Leute melden, die dir helfen können (und wollen). Sich durch 563 Zeilen Code durchzuforsten, ist nicht gerade das, was die meisten unter Unterhaltung verstehen. Passwort, 2 Ports, SoftUart, WLAN, BT, Intranet und ähnliches gehört mit Sicherheit nicht zu unbedingt nötigen Zutaten, zumindest nicht in diesem Stadium.
habe mich nun nach zwei tagen pause wieder dem Bootloader gewidmet, und habe den Fehler auf den ersten Blick erkannt. Manchmal sieht man vor lauter Bäumen den Wald nicht mehr... Nun das Problem war, dass ich beim Page löschen die Adresse der Page nicht definiert habe, als ohne Z-Pointer. Dies erklärt auch den Fehler den ich anfangs hatte, dass der Bootloader teilweise mit &hFF überschrieben wurde, und deshalb nur einmal funktionierte. Marc Vesely schrieb: > Die ganzen '#if' Diese sind nur für den Compiler relevant, je nach dem, ob die Konstante die Bedingung erfüllt wird der Code zwischen #if und #endif ebenfalls kompiliert. Marc Vesely schrieb: > Wenn du auf mich hören willst Auf jeden fall, besten Dank für deine Tips und Hilfe. Der Bootloader funktioniert nun so wie er soll.
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.