Hallo zusammen!
Habe ein Verständnisproblem und ich hoffe ihr könnt mir helfen.
Bisher stand immer am Anfang meiner FW der Interrupt Vektor.
Die ersten 4 Bytes davon sind der Stack Pointer, die weiteren 4 Bytes
die Startadresse.
Nun wollte ich "Meta Daten" meiner FW hinzufügen, die im Bootloader
ausgewertet werden soll. Deshalb müssen diese Informationen immer an der
selben Adresse stehen. Mittendrin ist blöd. Am Ende auch, da die Länge
der FW ja sich leicht verändert. "Also warum nicht am Anfang!?", dachte
ich mir.
Linker File angepasst: d.h. an den Anfang meine MetaDaten (mit fester
und bekannter größe gelegt), den Interrupt Vektor nach hinten geschoben.
Ohne Fehler kompiliert, gelinkt und geflasht.
Meine Metadaten standen da, wo sie sein sollten, deren Inhalt war auch
richtig. Auch die Adressen für den StackPointer und meiner Anwendung
stimmten.
Beim Starten der Applikation lande ich jedoch immer im
"DebugMon_Handler".
Kann man bitter jemand sagen, was ich falsch mache bzw. warum das nicht
so funktioniert wie ich es mir gedacht habe?
Danke & Grüße
Nali
Nali schrieb:> Kann man bitter jemand sagen, was ich falsch mache bzw. warum das nicht> so funktioniert wie ich es mir gedacht habe?
ohne den µC zu kennen, wird es verdammt schwer.
Nali schrieb:> Linker File angepasst: d.h. an den Anfang meine MetaDaten (mit fester> und bekannter größe gelegt), den Interrupt Vektor nach hinten geschoben.
Blöd nur dass die Hardware den an einer bestimmten Stelle erwartet.
Man lese sich mal die Beschreibung des Cortex-M4 durch, im Zweifel auf
der infocenter.arm.com Webseite.
Ein guter Platz für Firmware Infos ist hinter der Vektortabelle.
Hallo Rüdiger,
vielen dank für deine Antwort.
Das ist so nicht richtig zusammengefasst.
Am Anfang des gesamten Flashs (0x08000000) sitzt ja noch immer mein
Bootloader, der seinen eigenen SP (Offset: 0 Byte) und PC (Offset: 4
Byte) hat.
Der Bootloader weiß ja, wo sich das Hauptimage (0x08010000) befindet.
Bei diesem Image war bisher ebenfalls der Offset für den SP 0 Byte, also
0x08010000 und 4 Byte (respektive 0x08010004) für den PC.
Nun sind alle ein paar Bytes durch Anpassung des Linkerfiles nach hinten
geschoben worden. An 0x08010000 sitzen also nun meine Metadaten. Der SP
steht bei 0x0801000C der PC entsprechend bei 0x08010010. Habe extra
drauf geachtet, dass meine Metadaten vielfaches von 32bit/4 Byte sind,
damit es mit dem Padding keine Probleme gibt.
Der PC stimmt auch mit der im Linkeroutputfile angegebenen Adresse der
Startfunktion überein. Daher wundert mich, dass augenscheinlich alles
passt und harmoniert und es dennoch nicht funktioniert...
Viele Grüße
Nali
Nali schrieb:> Der Bootloader weiß ja, wo sich das Hauptimage (0x08010000) befindet.
Hast du dem Bootloader denn auch mitgeteilt, dass SP & PC nun an anderer
Position liegen?
Du schreibst, der Bootloader weiß es ja...also er wusste & nun mit neuem
Aufbau?
Adam P. schrieb:> Du schreibst, der Bootloader weiß es ja...also er wusste & nun mit neuem> Aufbau?
Natürlich! SP und PC werden richtig geladen. - Und zuvor werden auch
richtig die Metadaten ausgelesen ...
Moin,
"eigentlich" sollte deine Lösung dann auch funktionieren. Nur das du
halt beim Wechsel vom Bootloader zur Application die Adresse 0x0801000C
als Startadresse angeben musst (und nicht die 0x08010000 wie vorher).
(Und zusätzlich musst du den µC natürlich noch sagen, wo er die
Vectortabelle findet (bevor du irgendwelche Interrupts nutzt).
Mike R. schrieb:> Application die Adresse 0x0801000C> als Startadresse angeben musst (und nicht die 0x08010000 wie vorher).
Ähm ... ist das jetzt ein Test? Ich setze als Startadresse die Adresse,
die an der Adresse 0x08010010 liegt/abgespeichert ist.
Mike R. schrieb:> (Und zusätzlich musst du den µC natürlich noch sagen, wo er die> Vectortabelle findet (bevor du irgendwelche Interrupts nutzt).
Nochmal ... ähm ... Was? Wo? Wie?
Vermutlich liegt hier der Wurm begraben!
Nali schrieb:> Ähm ... ist das jetzt ein Test?
Zur Klarstellung:
1. SP wird mit dem Wert geladen der an 0x0801000C liegt
2. PC wird mit dem Wert geladen der an 0x08010010 liegt
richtig?
Adam P. schrieb:> Zur Klarstellung:>> 1. SP wird mit dem Wert geladen der an 0x0801000C liegt> 2. PC wird mit dem Wert geladen der an 0x08010010 liegt>> richtig?
Ja, richtig!
Aber deine Vermutung mit der Vektortabelle geht in die richtige
Richtung!
Wie soll ich es sagen? - Das Register VTOR nimmt den zusätzlichen Offset
nicht an!
Wie man im angefügten Screenshot sehen kann setze ich in den Int.Vektor
Adresse auf 0x08010010 und im Register selbt steht jedoch 0x08010000 .
Als Gegentest habe ich VTOR auf 0x08020010 gesetzt; im Register steht
aber "nur" 0x08020000.
Damit ist wohl die Ursache gefunden! - Nur der Grund ist mir nicht klar!
?:-O
Gruß
Nali
Nali schrieb:> . An 0x08010000 sitzen also nun meine Metadaten. Der SP> steht bei 0x0801000C der PC entsprechend bei 0x08010010. Habe extra> drauf geachtet, dass meine Metadaten vielfaches von 32bit/4 Byte sind,> damit es mit dem Padding keine Probleme gibt.
Klappt nicht. Bitte Doku zu Cortex M lesen, die Vektortabelle hat
strengeres Alignment - IIRC 128 oder 256 Byte. Siehe VTOR.
When setting TBLOFF, you must align the offset to the number of
exception entries in the vector table. The minimum alignment is 32
words, enough for up to 16 interrupts. For more interrupts, adjust the
alignment by rounding up to the next power of two. For example, if you
require 21 interrupts, the alignment must be on a 64-word boundary
because the required table size is 37 words, and the next power of two
is 64. See your vendor documentation for the alignment details for your
device.
aus
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/Ciheijba.html
Nali schrieb:> Äh ... warum hat Rüdiger nun seinen Post gelöscht!? Egal ...> Die Antwort passt auch auf die Antwort von dir, Jim. ;)
Ich hatte deinen Post nochmal etwas genauer gelesen, und dabei war mir
aufgefallen, dass meine Interpretation der Sache (wie auch Jim's
ursprüngliche) falsch und damit meine Antwort nicht sachdienlich war.
Sorry 4 the noise!
Ich denke auch, dass die alignment Sache den Kern trifft.
Zusätzlich würde ich noch einmal darüber nachdenken, die Metadaten
hinter die Vektortabelle zu legen.
Ansonsten musst du das nächste mal, wenn die Metadaten größer werden,
Bootloader und Programm anpassen und bist nicht mehr mit alten Versionen
kompatibel.
Jim M. schrieb:> Klappt nicht. Bitte Doku zu Cortex M lesen, die Vektortabelle hat> strengeres Alignment - IIRC 128 oder 256 Byte. Siehe VTOR.
Kommt hin ...
Alles was kleiner als 0x80 ist wird auf 0x00 "abgerundet".
Alles zwischen als 0x80 und 0xFF wird auf 0x80 "abgerundet".
Aus 0x08010037F wird also 0x080100300.
Aus 0x08020019F wird also 0x080200180.
0x080200500 bleibt bei 0x080200500 und 0x080200880 bleibt bei
0x080200880.
Mike R. schrieb:> Bootloader und Programm anpassen und bist nicht mehr mit alten Versionen> kompatibel.
Werde ich tun!
@ALL:
Vielen Dank für eure konstruktive Hilfe!
Hat Spaß gemacht! ;)
Grüße
Nali
Ich hab den Thread zwar nicht erstellt, aber da ich auch gerne
entsprechende Metadaten in der Firmware unterbringe:
Sowohl als auch.
Die Meta Daten sind ein const struct, das an der vorgegebenen Stelle
(hinter der Vectortabelle) platziert wird.
Zusätzlich habe ich einige Tools, die die erstellte FW durchlaufen und
einige Marker in diesem Struct ersetzen. (z.B. eine Checksumme einfügen)
Und drittens kann auch der Bootloader nach dem flashen noch bestimmt
Felder eintragen (Wenn die mit 0xFF initialisiert sind, geht das ohne
die Page noch einmal löschen zu müssen).
Mike R. schrieb:> Ich hab den Thread zwar nicht erstellt, aber da ich auch gerne> entsprechende Metadaten in der Firmware unterbringe:> Sowohl als auch.>> Die Meta Daten sind ein const struct, das an der vorgegebenen Stelle> (hinter der Vectortabelle) platziert wird.> Zusätzlich habe ich einige Tools, die die erstellte FW durchlaufen und> einige Marker in diesem Struct ersetzen. (z.B. eine Checksumme einfügen)> Und drittens kann auch der Bootloader nach dem flashen noch bestimmt> Felder eintragen (Wenn die mit 0xFF initialisiert sind, geht das ohne> die Page noch einmal löschen zu müssen).
Ich bin der TO und der Text könnte genau so gut auch von mir sein! :-D
Alles klar, danke.
Und was für Infos schreibt ihr da rein?
Version, Datum?
Habe sowas ähnliches, jedoch überleg ich grad, ob euer Ansatz eleganter
ist :-)
Meine erstellte FW läuft durch ein Tool und der FW wird ein Header
vorangestellt. Dieser wird durch den Bootloader extrahiert, geprüft etc.
und die FW (ohne Header) in den Flash kopiert.
@Mike
Platzierst du deine Metadaten immer direkt hinter den Int.Vektor, oder
irgendwo mit sicherem Abstand dahinter?
Ersteres hat ja die Gefahr, dass wenn man was am Int.Vektor ändert, z.B.
neue Interrupts hinzufügt und verwendet auch die Endadresse nicht mehr
stimmt.
Eine bestimmte Speicherstelle "irgendwo im sicheren Abstand dahinter",
fürh dazu, dass evtl. irgendwelche Codefragmente entstehen, da der
Linker eben an der Speicherstelle die Metadaten einfügen muss ...
Da ich den IAR Compiler incl. Start-Up files benutze, hat meine
Vetortabelle eine feste Länge (solange ich nicht den Controller
wechsel).
Beim STM32F415 liegt der Block z.B. an Adresse 0x08008188. Das ist das
erste Byte hinter das maximalen Vector Tabelle.
@Adam: Die Metadaten mit in den Flash zu schreiben hat einfach den
Vorteil, das der Bootloader bei jedem Start die Application prüfen kann
und es so nahezu unmöglich ist das gerät zu bricken.
Wenn das flashen fehlschlägt, bleibt das Programm auch nach einem
Neustart im Bootloader und man kann es noch einmal probieren.
Nali schrieb:> Adam P. schrieb:>> Version, Datum?>> +Länge des Bin-Files für Prüfsumme, Prüfsumme selbst, Statusflags, ...
+Firmware ID (um bei mehreren Geräten ein vertauschen der Firmware zu
verhindern), Version der Metadaten
Nali schrieb:> @Mike> Platzierst du deine Metadaten immer direkt hinter den Int.Vektor, oder> irgendwo mit sicherem Abstand dahinter?> Ersteres hat ja die Gefahr, dass wenn man was am Int.Vektor ändert, z.B.> neue Interrupts hinzufügt und verwendet auch die Endadresse nicht mehr> stimmt.> Eine bestimmte Speicherstelle "irgendwo im sicheren Abstand dahinter",> fürh dazu, dass evtl. irgendwelche Codefragmente entstehen, da der> Linker eben an der Speicherstelle die Metadaten einfügen muss ...
Bin zwar nicht Mike, aber hier meine Antwort:
Ich lege den Anker i.d.Regel direkt hinter das Ende der IVT.
Wer's am Rande der Legalität mag: Du kannst einen Zeiger auf die
Struktur auch an Vector 0 (initial SP) legen und nach dem Hochfahren den
SP explizit umsetzen (damit kannst Du Dir bis zur ersten stackbasierten
Operation Zeit lassen, natürlich aber so füh wie möglich). Aber Achtung:
FreeRTOS (und zweifellos auch Andere OS und Softwaren) trifft Annahmen
über das IVT layout, d.h. beim Hochstarten von FreeRTOS wird der SP über
Vector 0 der über VTOR zugreifabren IVT nochmals umgesetzt, d.h der
Startup des OS müsste manuell umgebogen werden.
Du kannst auch einen beliebigen immer unbenutzten Vektor als Zeiger auf
den Anker umbiegen oder deine Struktur mit einer Signatur absichern, die
niemals eine gültige Adresse sein kann und dann beim Hochfahren von 0
bis zu dieser Signatur suchen. Dann können deine Metadaten auch variabel
liegen (aber natürlich niemals hinter Codebeginn). All solche Sachen
sind aber tendentiell eher fehleranfällig. In meiner Philosophie ist
small=beautiful.
Ich habe im Beispielcode meines Buches Kapitel 9 eine
Beispielimplementatio n, die viel von dem abdeckt, was hier beschrieben
wurde (das ist keine Werbung, weil der Code kostenfrei und frei
zugänglich ist).
Mike R. schrieb:> @Adam: Die Metadaten mit in den Flash zu schreiben hat einfach den> Vorteil, das der Bootloader bei jedem Start die Application prüfen kann> und es so nahezu unmöglich ist das gerät zu bricken.> Wenn das flashen fehlschlägt, bleibt das Programm auch nach einem> Neustart im Bootloader und man kann es noch einmal probieren.
Wieso muss man das Rad immer wieder neu erfinden!?
Auch genau das sind meine Intensionen!
Mike R. schrieb:> +Firmware ID (um bei mehreren Geräten ein vertauschen der Firmware zu> verhindern), Version der Metadaten
"Ja" und "gute Idee"! ;-)
Ruediger A. schrieb:> Wer's am Rande der Legalität mag: Du kannst einen Zeiger auf die> Struktur auch an Vector 0 (initial SP) legen und nach dem Hochfahren den> SP explizit umsetzen (damit kannst Du Dir bis zur ersten stackbasierten> Operation Zeit lassen, natürlich aber so füh wie möglich). Aber Achtung:> FreeRTOS (und zweifellos auch Andere OS und Softwaren) trifft Annahmen> über das IVT layout, d.h. beim Hochstarten von FreeRTOS wird der SP über> Vector 0 der über VTOR zugreifabren IVT nochmals umgesetzt, d.h der> Startup des OS müsste manuell umgebogen werden.>> Du kannst auch einen beliebigen immer unbenutzten Vektor als Zeiger auf> den Anker umbiegen oder deine Struktur mit einer Signatur absichern, die> niemals eine gültige Adresse sein kann und dann beim Hochfahren von 0> bis zu dieser Signatur suchen. Dann können deine Metadaten auch variabel> liegen (aber natürlich niemals hinter Codebeginn). All solche Sachen> sind aber tendentiell eher fehleranfällig. In meiner Philosophie ist> small=beautiful.
Ähm ... wird mir zu kompliziert ... Da kommt dann schnell "Error in
Layer 8" hinzu!
Ruediger A. schrieb:> (das ist keine Werbung, weil der Code kostenfrei und frei> zugänglich ist).
Von deinem Buch ist ja nicht einmal die Leseprobe kostenlos! :-P
(Habe dich schon gegoogelt. :-D)
Nali schrieb:> @Mike:> Nutzt du auch zusätzlich einen festen und eindeutigen Startidentifier> deiner Metadaten?
Nein, ich verlasse mich darauf, das das strcut immer an der Adresse
liegt, an der ich es erwarte.
Mike R. schrieb:> Das ist jetzt zwar eine alte Version, aber so sieht das ganze ungefähr> aus
Diese Ähnlichkeit! - Verblüffend! :-D
Nur bei der Positionierung unterscheiden wir uns!
Ich verwende den Pragma-Operator:
Nali schrieb:> Sollte man nicht die Meta-Versionsnummer ganz an den Anfang legen?
Sollte man auf jeden Fall tun.
Wie gesagt, das ist eine alte Version.
Die hat noch keine Versionsnummer für die Metadaten.
Das Meta in der von mir genannten Struktur gehört zur Firmware Versions
Nummer.
Nali schrieb:> Ruediger A. schrieb:>> uhm, falsch:>>>> https://books.google.de/books?id=8ra8DQAAQBAJ&pg=PR3#v=onepage&q&f=false>> Hmmm ... Bin mal kurz über das Buch rüber gescrollt. Schein ganz nett zu> sein! ;-)> Was mir auffällt, trotz Cortex-spezifika sehe ich nirgends eine> Beschreibung der HW-Faults (HardwareFault, Bus-Fault, Usage Fault),> obwohl du "Faults" thematisierst.
Hi Nali,
beantworte ich gerne, aber lieber offline, sonst hat das Ganze zu sehr
ein Geschmäckle von Hijacken des threads für Werbezwecke... schick mir
am Besten eine PM, dann können wir das Offline weiterführen!
Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.
Wichtige Regeln - erst lesen, dann posten!
Groß- und Kleinschreibung verwenden
Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang