Hallo, ich stehe gerade vor folgendem Problem und würde mich über einige Anregungen freuen und zwar entwickle ich gerade auf einem ARM Cortex M3, und zwar ein STM32 und bin gerade dabei einen schon vorhandenen Bootloader auf eine kryptographisch gesicherte Version umzubauen also AES256 und HMAC mit SHA1, der Krypto Code und alles laufen auch aber jetzt würde ich das ganze gerne dahingehend optmieren, dass Applikation und Bootloader die Kryptofunktionen gemeinsam nutzen und in Zukunft vielleicht auch noch SPI oder sonst was von der Treiberschicht. Denn die Krypto Funktionen sind ca 6KB groß und die will ich nur ungern doppelt hineinkompilieren weil sie die Applikation auch braucht und die sich eh nicht mehr ändern werden. Soweit so gut, nur wie geht das am einfachsten? Was mir mal so einfallen würde: 1) Beides gemeinsam kompilieren, Sections für Bootloader+Lib und Hauptapplikation, könnte dann auch den NVIC Table sharen. Gefällt mir recht gut, aber wie mach ich das mit den Sections für initialisierte Variablen, nicht initialisierten Variablen, globalen Variablen, die müssen ja für den Bootloader+Libs teil auch wenn ich an der Applikation schraube immer unverändert bleiben. Für den Code geht das ja einfach, aber globale Variablen und der Initialisierungsteil machen mir da Sorgen? 2) getrennt kompilieren, so ca wie ich es jetzt mache, dann müsste ich aber auch irgendwie schauen, dass sich globale Variablen nicht überschneiden, die Initialisierung könnt ich mir sparen weil beim Bootloader teil die globalen Sachen eh immer neu initialisiert werden, vielleicht wärs auch eine Optione alle globalen Variablen bei der Krypto Lib zu vermeiden, macht vieles einfacher. Aber wie sag ich dann meiner Hauptapplikation beim Linken wo sie die Funktionen findet? würde mich über einige Anregungen dazu freuen, mfg thomas
Ich würde einen festen Einsprungvektor bauen, der immer auf die gleiche Adresse geladen wird. Von dort wird im Bootloader auf die eigentliche Funktion gesprungen. Globale Variablen sollten diese Funktionen komplett meiden, dann bist du das Problem ebenfalls los. (Der Bootloader selbst kann natürlich globale Variablen benutzen, wenn er läuft, läuft ja die Applikation nicht.) Die Adressen des Einsprungvektors kannst du über passend zurecht gebogene Zeiger in einer Headerdatei deiner Applikation zur Verfügung stellen, ungefähr so:
1 | typedef int (*foo_t) (const char *); |
2 | static const foo_t foo = (foo_t)0x1234; |
Die Applikation kann dann daher kommen und foo() wie eine ganz normale Funktion behandeln:
1 | int
|
2 | runfoo(const char *s) |
3 | {
|
4 | return 42 + foo(s); |
5 | }
|
danke erstmal für die Anregung. Ich glaub ich werde es so machen: Bootloader+Lib und Applikation+Lib getrennt kompilieren. Alles was gemeinsam verwendet wird werde ich als statische Lib kompilieren und mittels Linker Script in eine eigene Section legen, hier muss ich nur noch schauen, dass auch alle Teile der Lib gelinkt werden bzw dass nur ein *.o in der Lib ist, sollte soweit ich gesehen habe aber mit dem use Attribut bei Funktionen gehen. Bei der Hauptapplikation werd ich dann beim erstellen wieder die section mit ojb-copy aus dem Hex/Bin file rauslöschen. Sollte das so funktionieren?
Weiß nicht, ich find's reichlich umständlich und fehleranfälliger als die Sache mit dem Einsprungvektor. Spätestens, wenn du nach einiger Zeit die nächste Version des Bootloaders implementieren musst und dann "im Feld" zwei verschiedene Versionen mit verschiedenen Adressen für die Bibliotheksfunktionen hast, wirst du mächtig ins Rudern kommen.
Hmm, naja das mit den verschiedenen Adressen, wenn sich der Bootloader ändert kann ich ja so oder so nicht beeinflussen, da muss ich die Vektoren auch anpassen. Aber wenn ich Applikation und Bootloader immer gegen die selbe Lib linke, muss ich mir die Vektoren nicht aus dem Map File saugen. Sondern ich bekomm sie beim Linken automatisch.
Man kann Bootloader und Applikation nicht zusammen manschen, das geht in die Hose. Der Bootloader könnte einen SW-Interrupt benutzen und dort nen API-Call eintragen. Und die Applikation ruft dann mit Funktionsnummer das API auf und kriegt nen Returnwert über den Erfolg. Dazu müssen aber die API-Funktionen so geschrieben werden, daß sie keinen RAM belegen. Alle temporären Variablen müssen auf dem Stack abgelegt werden. Benötigt das API statische Variablen, müssen die von der Applikation mit einen API-Init Call angelegt werden. Z.B. es wird der Pointer auf malloc übergeben damit das API es aufrufen kann. Peter
Thomas H schrieb: > aber > > jetzt würde ich das ganze gerne dahingehend optmieren, dass Applikation > > und Bootloader die Kryptofunktionen gemeinsam nutzen und in Zukunft > > vielleicht auch noch SPI oder sonst was von der Treiberschicht. Man kann sowas gut via Software Interrupt lösen. Der Bootloader installiert entsprechende Crypto-Funktionen über den Software Interrupt Handler, die Anwendung erzeugt dann einfach einen Software Interrupt zum Ausführen dieser Funktionen. Bin mir aber nur nicht sicher ob ARM Cortex M3 sowas bietet
Thomas H schrieb: > Hmm, naja das mit den verschiedenen Adressen, wenn sich der Bootloader > ändert kann ich ja so oder so nicht beeinflussen Du hast das immer noch nicht verstanden. Du baust einen Einsprungvektor auf eine feste Adresse (bspw. ganz an den Anfang oder kurz vor das Ende des Bootloaders). Dessen Adresse ändert sich nie wieder und die Reihenfolge seiner Einträge auch nicht. Die Applikation kennt damit ausschließlich diese Adressen. Dieser Vektor wiederum verzweigt auf die tatsächlichen Adressen im Bootloader, mit einfachen Sprüngen. Die werden dann vom Linker aufgelöst (beim Linken des Bootloaders). Wenn sich in einer nächsten Version des Bootloaders diese Sprünge ändern, interessiert das die Applikation kein bisschen.
klaus schrieb: > Man kann sowas gut via Software Interrupt lösen. Der Bootloader > installiert entsprechende Crypto-Funktionen über den Software Interrupt > Handler, die Anwendung erzeugt dann einfach einen Software Interrupt zum > Ausführen dieser Funktionen. Bin mir aber nur nicht sicher ob ARM Cortex > M3 sowas bietet Natürlich gibt es beim Cortex-M3 auch Software Interrupts, die bei ARM jetzt generell SuperVisor Call (SVC) genannt werden. Die alte Bezeichnung führte wahrscheinlich zu Verwechslungen mit Software Triggered Interrupts (STI), die einen ganz anderen Mechanismus verwenden. Die Frage ist, was die Applikation machen soll. Soll sie eventuell eigene SVC bereitstellen? Dann wird das mit den SVC im boot loader schwierig (man könnte auf STI ausweichen, falls vorhanden). Ansonsten ist das mit SVC eine saubere Sache. Ein anderer Ansatz wäre es, die API Funktionen mit dem boot loader in einen definierten Speicherbereich zu linken, und deren Adressen beim späteren Linken der Applikation zu laden (--just_symbols) Gruß Marcus
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.