Forum: Mikrocontroller und Digitale Elektronik ATmega328p fehlerhafte UART-Anzeige mit bootloader


von Julien (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
ich bin recht neu in der Mikrocontrollerprogrammierung, daher möchte ich 
mich vorab für mein rudimentäres Wissen entschuldigen (und so sieht für 
die Profis hier sicher auch mein Programm aus). Ich bringe mir dabei 
alles selbst, hauptsächlich mit Hilfe dieses Forums, bei aber für mein 
Problem habe ich nichts passendes gefunden.
Ich habe grade angefangen mit einem UART bootloader zu experimentieren 
und dazu das GCC-Tutorial genutzt (danke an den Ersteller). Ich nutze 
AtmelStudio 7 und das ganze läuft auf einem ATmega328p.

Nach einigen Stunden habe ich den bootloader zum laufen gekriegt und war 
auch sehr glücklich darüber. Wenn ich dann mein Programm damit flashe 
scheint auch alles zu gehen. Ich habe mir eine kleine UART Diagnose für 
die Eingänge gebastelt aber leider zeigt er beim "Reload" und "Semi" 
Eingang auf meinem Terminal einige "FF" Zeichen an. Ich habe keine 
Erklärung dafür, wenn ich das Hauptprogramm mittels ISP direkt drauf 
flashe funktioniert es einwandfrei.

Im bootloader Programm habe ich in den "Flash segment" Bereich des 
Linkers folgendes eingetragen ".text=0x3800". Das ist die Word-adresse 
entsprechend der Fuses die ich gesetzt habe.

Im bootloader, wie auch im Hauptprogramm habe ich die uart.h und 
uart.cpp eingefügt.

Wie gesagt, bin ich Anfänger und hoffe, dass ich alle nötigen Dateien 
angehängt habe.

Vielen Dank schon einmal.

von Julien (Gast)


Lesenswert?

Hallo,

also ich bin mir grade etwas unsicher warum noch niemand geantwortet 
hat. Vielleicht habe ich das Problem nicht genug beschrieben oder es 
fehlen noch Daten oder ich habe nicht genug Geduld.

Ich würde mich nach wie vor sehr über Hilfe freuen.

von Patrick L. (Firma: S-C-I DATA GbR) (pali64)


Lesenswert?

Ich tippe auf falsch eingestellte Baudrate/Parität/Bitzahl usw....
Atmrga & Co sind nicht mein Gebiet...
Kann dir also da kaum Helfen.

: Bearbeitet durch User
von Veit D. (devil-elec)


Lesenswert?

Hallo,

entweder das oder man probiert zur Gegenkontrolle einen getesteten 
Bootloader aus. Wobei auch hier die Einstellungen für diesen beachtet 
werden müssen. Für verschiedene Baudraten ...
https://github.com/MCUdude/MiniCore/tree/master/avr/bootloaders/optiboot_flash/bootloaders/atmega328p
Je nach Ergebnis dann die Schlussfolgerung ziehen.

von Julien (Gast)


Lesenswert?

Erst ein mal vielen, vielen Dank für eure Antworten.
Mit Arduino kenne ich mich gar nicht aus und ich weiß grade nicht wie 
ich das .hex file an den definierten Speicherort flashen kann.

Ich übertrage mehrere Sachen per USART zur Diagnose. Alle anderen 
funktionieren einwandfrei und wie gesagt, auch die im bild fehlerhaften 
Stellen funktionieren einwandfrei, wenn ich es ohne Bootloader, sondern 
mit ISP flashe mit den gleichen baud und anderen Einstellungen.

Kann es vielleicht sein, dass wenn ich das Programm mit dem Bootloader 
flashe es beim USART Puffer beschreiben auf Speicherbereiche zugreift in 
den bereits was steht und das byte dann ff ist? Dafür kenne ich mich zu 
wenig aus.

Oder ist es vielleicht so, dass weil ich die uart.h/.cpp im bootloader, 
sowie im Hauptprogramm identisch habe es damit durcheinander kommt?

von Stefan F. (Gast)


Lesenswert?

Julien schrieb:
> ich weiß grade nicht wie
> ich das .hex file an den definierten Speicherort flashen kann.

Die Adressen solltem im Hex File selbst drin stehen. Das Dateiformat ist 
bei Wikipedia erklärt, du kannst es mit dieser Info manuell überprüfen.

Bevor man neue Daten in den Flash Speicher schreibt, muss er 
selbstverständlich gelöscht werden. Das sollte der Bootloader erledigen.

0xFF ist der gelöschte Zustand.

Du kannst den Speicher mit dem ISP Programmieradapter Auslesen und so 
prüfen, ob das erwartete Programm vollständig drin ist. Wenn nicht, 
waren entweder deine Hex Dateien fehlerhaft oder der Bootloader.

Warum fummelst du überhaupt mit einem Bootloader herum. Ich würde mir 
das nur antun, wenn ich einen wichtigen Grund dazu hätte. Und dann würde 
ich immer nur den Bootloader von Arduino nehmen, denn der hat sich 
millionenfach bewährt.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

der Bootloader hat mit dem eigentlichen Programm nichts zu tun. 
Überschrieben werden kann nur etwas, wenn die Fuse Eintellungen nicht 
stimmen. Sprich der Bootloaderbereich zu klein oder gar nicht gesetzt 
ist. Kontrolliere bitte die Fuse Einstellungen. Im schlimmsten Fall ist 
dein Bootloader zu groß. Deswegen teste erstmal mit bewährten 
Bootloader, danach kann man eigene Varianten ausprobieren.

Auch wenn die verlinkten Bootloader Dateien im weiten Sinne für Arduino 
sind, haben diese nichts mit Arduino zu tun. Das muss man gedanklich 
trennen. Das sind nur weitere Varianten für verschiedene Taktraten und 
Bautraten. Flashen tust du die ganz normal mit deinem ISP Programmer. 
Dabei sollte immer der gesamte Flash gelöscht werden, wenn es keine 
anderen Gründe gibt. avrdude Option -e.

Den kompletten Überblick gibts hier.
https://www.mikrocontroller.net/articles/AVR_Bootloader_in_C_-_eine_einfache_Anleitung

von Matthias (Gast)


Angehängte Dateien:

Lesenswert?

ich habe bei mir nach Tagen suchen den optiboot loader installiert, der 
bei github zu finden ist in verschiedenen Varianten, bei mir dann am 
Schluss der 8MHz mit 115200. Der funkitioniert mit der arduino ide 
zusammen, wenn man das generierte hexfile selbst mit avrdude hochlädt.
./upload.sh hexfile.hex
optiboot findest Du hier:
https://github.com/MCUdude/MiniCore/tree/master/avr/bootloaders/optiboot_flash/bootloaders/atmega328p

von Julien (Gast)


Angehängte Dateien:

Lesenswert?

Hey,
erst mal erneut vielen, vielen Dank für eure Antworten. Ich habe mir mal 
den Flash vom Programm das ich mit dem Bootloader drauf gespielt habe 
ausgelesen und die fehlerhafte Zeile gefunden (Bild).

Der Fehler taucht auch bei mehrmaligem flashen immer an der gleichen 
Stelle auf. Ich bin jetzt dabei heraus zu finden warum das so ist. Ich 
bin mir nicht ganz sicher, schließlich hatte ich noch keine Probleme 
damit, aber ich habe keinen Quarz am Controller. Vielleicht versuche ich 
ihm mal einen Takt von außen mit einem Quarz vor zu geben.
Ich schaue mir auch noch mal genau meinen Bootloader an.

Falls noch jemand einen Vorschlag hat, oder ihm das bekannt vor kommt 
bin ich natürlich für jeden Tipp dankbar.

von S. Landolt (Gast)


Lesenswert?

Das ist offenbar der Start der String-Konstanten; aber was daraus folgt 
- keine Ahnung.

von Stefan F. (Gast)


Lesenswert?

Die Frage klingt vielleicht blöd aber wir hatten das schon einmal: Hast 
du Abblock-Kondensatoren direkt am Mikrocontroller? Gerade beim 
Flashen ist eine stabile Stromversorgung wichtig und die Stromaufnahme 
höher als sonst.

Steckbretter zwischen IC und Abblock-Kondensator sind ungünstig, wegen 
der hohen Kontaktwiderstände und Leitungslängen.

von S. Landolt (Gast)


Lesenswert?

> stabile Stromversorgung
Schon, aber
> Der Fehler ... immer an der gleichen Stelle

Kann ich mir eigentlich nicht vorstellen.
  Hätte eher vermutet, dass da irgendetwas nicht mit dem LineFeed zu 
Beginn des Blockes zurechtkommt.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

Fuse kontrollieren.

von Julien (Gast)


Angehängte Dateien:

Lesenswert?

>Hallo,
>
>Fuse kontrollieren.

Könntest du das bitte etwas genauer umschreiben?
Ich habe die aktuellen Einstellungen mal als Screenshot hinzugefügt.

von Stefan F. (Gast)


Lesenswert?

Julien schrieb:
> Könntest du das bitte etwas genauer umschreiben?
> Ich habe die aktuellen Einstellungen mal als Screenshot hinzugefügt.

Ich denke er meinte die markierte BOOTSZ (soll größer oder gleich der 
tatsächlichen Größe des Bootloader) und darunter BOOTRSR (soll an sein).

von Veit D. (devil-elec)


Lesenswert?

Hallo,

genau das meinte ich und wollte ich sehen. Aber das passt soweit.
Ansonsten steht dazu laut meiner Meinung alles hier.
https://www.mikrocontroller.net/articles/AVR_Bootloader_in_C_-_eine_einfache_Anleitung

Nur wenn du sagst das ohne Bootloader alles funktioniert und mit 
Bootloader nicht, dann kann es ja nur an deinem Bootloader liegen. Hast 
du schon einen passenden der fertigen Bootloader probiert?

Wenn der interne RC zu schief takten würde das eine fehlerhafte 
Übertragung zu Stande kommt, dann dürfte die Serielle nie funktionieren. 
Würde ich erstmal ausschließen.

Mit deinem Inhaltsvergleich kann ich mir aktuell nichts zusammenreinem. 
Möglicherweise sind das Reste vom vorherigen flashen, weil nicht 
komplett gelöscht. Der Bootloaderbereich liegt ja ganz hinten im Flash, 
den kann man nicht so einfach überschreiben.

Mehr kann ich aus der Ferne nicht dazu sagen.

von Stefan F. (Gast)


Lesenswert?

115200 Baud @ 8 MHz ist schon mit Quarz grenzwertig. Mit R/C Oszillator 
würde ich lieber eine Baudrate wählen, bei der die Abweichung durch den 
Frequenzteiler geringer ist. 38400 ist gut. Siehe im Datenblatt 
"Examples of Baud Rate Setting".

von S. Landolt (Gast)


Lesenswert?

> 115200 Baud

Woher kommt dieser Wert?
Im Bootloader vom Anfang lese ich "#define BOOT_UART_BAUD_RATE 
9600".

von Stefan F. (Gast)


Lesenswert?

S. Landolt schrieb:
> 115200 Baud

Aus meiner Phantasie, weil das die Standard Baudrate des neuen Arduino 
Bootloaders ist. Wollte nur drauf hinweisen, dass nicht alle Baudraten 
gleich gut sind. Niedriger ist auch nicht zwangsläufig besser. Lieber 
ausrechnen auf die Tabellen im Datenblatt gucken.

von S. Landolt (Gast)


Lesenswert?

Also Quarz erschiene mir auch sinnvoller, bei einem ATmega328P mit 
seinen '10 % factory calibration', das nur am Rande.

Aber, auch wenn ich mich wiederhole: auffällig ist doch, dass der Fehler 
exakt dort auftritt, wo ein LineFeed zu Beginn einer Speicherseite 
geschrieben werden soll - da sollte Julien seinen Bootloader mal genauer 
anschauen.

von S. Landolt (Gast)


Lesenswert?

Hehe - er könnte ja mal probehalber aus seinem "\r\nTrigger: " ein 
"\r\nTrig ger: " machen und schauen, was passiert.

(... und überhaupt sich dann von der virtuellen Ballerei verabschieden)

von S. Landolt (Gast)


Lesenswert?

Landolt formulierte schlecht:
> wo ein LineFeed zu Beginn einer Speicherseite geschrieben werden soll

Besser wäre:
wo zu Beginn einer neuen Speicherseite ein innerhalb des Programmes 
stehendes LineFeed eintrifft.

von Julien (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
noch mal vielen Dank für eure Denkanstöße.
>Besser wäre:
>wo zu Beginn einer neuen Speicherseite ein innerhalb des Programmes
>stehendes LineFeed eintrifft.
Ich habe nun mal alle LineFeeds und "\033[2J" raus genommen. Der Fehler 
wandert zwar weiter, er ist aber immer noch vorhanden. Wie man auf dem 
Bild sehen kann, wandert er immer mit der "unvollständigen" Zeile und 
tritt genau eine Page später auf. Das Problem liegt auf jeden Fall in 
meinem Bootloader.
Wie gesagt bin ich eher Anfänger und habe mich an diese Anleitung und 
Bootloader gehalten:
https://www.mikrocontroller.net/articles/AVR_Bootloader_in_C_-_eine_einfache_Anleitung

von Stefan F. (Gast)


Lesenswert?

Warum nimmst du nicht endlich den Bootloader von Arduino?

von S. Landolt (Gast)


Lesenswert?

Es geht also um die letzte Speicherseite - mal in der Gegend "/* 
Dateiende -> schreibe Restdaten */" suchen.
(ich mit meinem Assembler tue mich da schwer)

von S. Landolt (Gast)


Lesenswert?

Vielleicht ist das jetzt dümmlich, aber: in write_page verstehe ich die 
Reihenfolge von _delay_ms und program_page nicht - ich hätte es genau 
umgekehrt gemacht.

von S. Landolt (Gast)


Lesenswert?

Stefan Frings protestierte:
> Warum nimmst du nicht endlich den Bootloader von Arduino?

"Jeder soll nach seiner Façon selig werden."

von Julien (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Warum nimmst du nicht endlich den Bootloader von Arduino?

Weil ich den booloader gerne starten möchte, wenn PB7 auf GND gezogen 
ist. Ist das nicht der Fall soll das Hauptprogramm starten. Kann ich den 
Arduino bootloader so modifizieren?
Ich habe den bootloader nun schon mit dem AtmelStudio drauf geflashed 
aber wenn ich den controller starte kommt nichts im UART Terminal.
Habe dann die Arduino IDE runter geladen und versucht damit den 
bootloader drauf zu packen. Da hat er über falsch gesetzte lock fuses 
gemeckert. Die sind aber nicht gesetzt (default) und ich denke, dass er 
das macht weil ich den internen 8Mhz clock nutze. Außerdem habe ich 
jetzt keinen Zugriff mehr auf den controller und musste nen neuen 
nehmen. Ich scheine wohl wahrlich zu blöde für die Arduino IDE zu sein. 
Ich finde da nen ganzen Haufen von Einstellungsmöglichkeiten nicht, die 
ich im AtmelSudio habe.

S. Landolt schrieb:
> Es geht also um die letzte Speicherseite - mal in der Gegend "/*
> Dateiende -> schreibe Restdaten */" suchen.
> (ich mit meinem Assembler tue mich da schwer)

Das habe ich mir nach deinem Hinweis auch genau angesehen, aber das ist 
es nicht. Nach der "kurzen" Zeile im .hex file schreibt der die page 
korrekt in den flash. Der Anfang der nächsten Page erzeugt den Fehler. 
Es ist meiner Vermutung nach irgend etwas im Bereich "/* Füllen des 
Flash-Puffers mit dem "alten" Inhalt der Page */
memcpy_PF(flash_data, flash_page, SPM_PAGESIZE);" falsch aber ich kriege 
es nicht zu fassen. Habe nun viel mit UART versucht zu diagnostizieren, 
die ganzen counter mit geplottet und deren Funktion versucht zu 
verstanden, aber ich krieg nicht raus was der Fehler ist. Ich kann mir 
gut vorstellen, dass es am ATMega328p liegt, das Tutorial ist ja auf den 
Mega88 bezogen und selbst den tutorial Beispielcode flasht er mit exakt 
dem gleichen Fehlerbild.
Schreibe Restdaten ist nur für die aller letzte Zeile zuständig.

von Stefan F. (Gast)


Lesenswert?

Julien schrieb:
> Weil ich den booloader gerne starten möchte, wenn PB7 auf GND gezogen
> ist. Ist das nicht der Fall soll das Hauptprogramm starten. Kann ich den
> Arduino bootloader so modifizieren?

Du meinst aus dem laufenden Betrieb heraus? Das kann man mit dem 
Watchdog machen. Watchdog starten und dann in eine Endlosschleife gehen, 
er resetted dann den Chip, so dass der Arduino Bootloader startet.

Oder meintest du, dass der Bootloader beim Start nur aktiv sein soll, 
wenn PB7=LOW ist? Ich glaube dazu müsstest du dessen Quelltext 
editieren, was auch kein Problem sein sollte. Der ist ja öffentlich 
zugänglich, andere haben auch schon Varianten davon implementiert z.B. 
für AVR Modelle die nicht zu Standardumfang von Arduino gehören.

Ich benutze in meinen eigenen Projekten nur selten Botoloader. Aber da 
ist dann immer der Bootloader von Arduino, selbst wenn mein 
Anwendungsprogramm gar nicht mit Arduino gemacht wurde. Und zwar mache 
ich das, weil ich Avrdude mag und weis dass Avrdude den Arduino 
Bootloader unterstützt. Ich habe gar keine Lust mich mit anderen 
speziellen PC Programmen (für den Bootloader) auseinander zu setzen. Die 
meisten sind eh nur für Windows verfügbar, das nutze ich auch nicht 
freiwillig.

Julien schrieb:
> Ich scheine wohl wahrlich zu blöde für die Arduino IDE zu sein.
> Ich finde da nen ganzen Haufen von Einstellungsmöglichkeiten nicht, die
> ich im AtmelSudio habe.

In der GUI kann man nur wenig konfigurieren. Das meiste findet man in 
diversen Textdateien wieder. Arduino ist halt nicht so flexibel, wie 
deine Art zu programmieren. Dafür ist es einfacher.

von S. Landolt (Gast)


Lesenswert?

Vermutlich komme ich hinterher wie die alte Fastnacht, egal:

Julien schrieb:
> Es ist meiner Vermutung nach irgend etwas im Bereich "/* Füllen des
> Flash-Puffers mit dem "alten" Inhalt der Page */
> memcpy_PF(flash_data, flash_page, SPM_PAGESIZE);" falsch

So ist es, die Stelle ist falsch: 'case PARSER_STATE_TYPE'.
Durch die 'verkürzte' Zeile im Intel-Hex-File wurde an dieser Stelle 
flash_data wieder teilweise gefüllt, was dann durch das memcpy_PF 
überschrieben wird.
  Konkret im ersten Beispiel (mit den LF&CR): die 'verkürzte' Zeile ist 
2 Bytes kürzer, diese werden aus der nächsten Zeile geholt, anschließend 
wird flash_data mit 16-2= 14 Bytes gefüllt, die aber werden zu Beginn 
der darauffolgenden Zeile 'übergebügelt', dort stehen dann 
fälschlicherweise 14 'FF's.

Der Programmteil mit dem memcpy_PF muss wohl irgendwo direkt nach 
write_page stehen.

von Julien (Gast)


Lesenswert?

Hallo,

erst ein mal vielen, vielen Dank für all eure Hilfe. Ich hasse es immer, 
wenn man im Forum nach ähnlichen Problemen sucht und am ende einfach nur 
ein "habs hin gekriegt" steht und nicht wie. Daher hier mal was ich 
gemacht habe:

Grundsätzlich sei gesagt, dass ich das Programm aus dem Tutorial benutzt 
habe. Zunächst habe ich versucht so gut es geht zu verstehen was es so 
macht und konnte das Problem auf "memcpy_PF" eingrenzen. Zunächst habe 
ich versucht zu verstehen wie es funktioniert und warum es dann doch 
nicht funktioniert. Irgend wann habe ich mir gesagt, dass es doch alles 
keinen Sinn macht und wollte meinen eigenen Bootloader schreiben. Dazu 
habe ich den Großteil wieder verwendet, allerdings ganz ohne memcpy_PF.
Ich warte auf das Startzeichen ":"
Ich werte Länge, Speicherort und Hex-Typ aus und speichere sie mir in 
Variablen nachdem ich sie in num umgewandelt habe (so wie im Programm 
vom Tutorial)
Dann speichere ich die in num umgewandelten Datenbytes in einen Buffer 
und schließlich noch die Checksumme mit der ich die Zeile prüfe.
Das wiederhole ich bis ich eine Page voll habe und schreibe die dann in 
den Flash.
So weit der Regelfall. Einige mehr Versuche brauchte ich für den Fall, 
dass die Hexzeile kürzer ist. Im Grunde fülle ich die kürzere Zeile mit 
den Zeichen der nächsten Zeile auf und schreibe dann bei einer 
vollständigen Page eben diese.
Die darauf folgende Pagewird wieder wie gewohnt gefüllt, dann aber eben 
an die im hex-file stehende Adresse geschrieben.
Ach ja, wichtig ist noch, dass ich nach dem Page schreiben meinen 
Datenpuffer mit 0xFF überschreibe. So schreibe ich keinen Datenmüll in 
die letzte (meist unvollständige) Page des Programms.
Zuletzt erkenne ich noch den Hex-Type 01 und beende den Bootloader.

Mit einigen Beispielcodes hat es geklappt. Ich werde nun eine ganze 
weile die Programme mit dem ISP-Programmer auslesen und prüfen ob nicht 
doch irgend etwas schief läuft.
Zuletzt habe ich noch die Hex-Types 02 und 04 heraus genommen, da dieser 
Bootloader nur für den Mega328p sein soll und ich so den Bootloader auf 
gute 1900byte Größe drücken konnte. So reicht es, wenn der Bootbereich 
1024words groß ist und ich eben so noch mal 2048byte Programmspeicher 
frei mache.

Ich weiß jetzt ganz genau wie mein Bootloader funktioniert und kann nach 
belieben alles ändern und anpassen wie ich es mag, außerdem konnte ich 
dabei viel lernen.

von Julien (Gast)


Lesenswert?

Ah, ich finde grade nicht wie ich meinen Beitrag editieren kann.

Ich habe geschrieben, dass ich die unvollständige Zeile mit den bytes 
der darauf folgenden Fülle. Das ist nicht so, weil es (natürlich) nicht 
funktioniert hat. Ich fülle die unvollständige Zeile mit 0xFF und 
schreibe die Page. Anschließend fülle ich den Buffer normal weiter mit 
den darauf folgenden Hex-Zeilen und schreibe die Page aber an die neue 
Adresse (dort wo ich angefangen habe mit 0xFF zu füllen). So 
funktioniert es (vermutlich sagen die Profis "ja, wie auch sonst", aber 
für mich ist es nen ziemlicher Erfolg).

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.