Forum: Mikrocontroller und Digitale Elektronik Probleme mit Bootloader bei ATmega328p


von Michael L. (nightflyer88)


Angehängte Dateien:

Lesenswert?

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.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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 ?

von Michael L. (nightflyer88)


Lesenswert?

Bootloader startet bei Adresse 0x3C00

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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
von Michael L. (nightflyer88)


Angehängte Dateien:

Lesenswert?

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...

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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.

von Michael L. (nightflyer88)


Angehängte Dateien:

Lesenswert?

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).

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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.

von Michael L. (nightflyer88)


Lesenswert?

funktioniert auch nicht. braucht es 2mal SPM ? Nach dem RWWSRE nochmal 
SPM ?

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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.

von Michael L. (nightflyer88)


Lesenswert?

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.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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
von Michael L. (nightflyer88)


Lesenswert?

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

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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.

von Michael L. (nightflyer88)


Angehängte Dateien:

Lesenswert?

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.

von Michael L. (nightflyer88)


Lesenswert?

solange ich keine interrupts im Bootloader habe und ausgeschaltet sind, 
ist doch das IVSEL-bit nicht zu beachten ?

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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
von Michael L. (nightflyer88)


Lesenswert?

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...

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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
von Michael L. (nightflyer88)


Lesenswert?

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 ?

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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
von Michael L. (nightflyer88)


Angehängte Dateien:

Lesenswert?

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.

von Michael L. (nightflyer88)


Angehängte Dateien:

Lesenswert?

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.

von Charly B. (charly)


Lesenswert?

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 ?

von Michael L. (nightflyer88)


Lesenswert?

USBasp

von Dieter M. (Gast)


Lesenswert?

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)

von Michael L. (nightflyer88)


Lesenswert?

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.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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 ?

von Michael L. (nightflyer88)


Angehängte Dateien:

Lesenswert?

anbei der Programm Code

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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.

von Michael L. (nightflyer88)


Lesenswert?

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
Noch kein Account? Hier anmelden.