Forum: Compiler & IDEs Bootloader und Applikation gemeinsam Compilieren


von Thomas H (Gast)


Lesenswert?

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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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
}

von Thomas H (Gast)


Lesenswert?

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?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Thomas H (Gast)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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

von klaus (Gast)


Lesenswert?

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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

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