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