Forum: Mikrocontroller und Digitale Elektronik Zeitunterschied einer Datei beim Ausführen von mehreren Dateien oder einer


von Alexander F. (itfreak12)


Lesenswert?

Hallo,
ich hab auf mehreren Mikrocontrollern das Problem, dass ich, wenn ich 
eine Datei und die darin enthaltenen Funktionen einzeln ausführe eine 
andere Laufzeit erhalte, als wenn ich diese Datei als eine von mehreren 
ausführe. Die einzelnen Module wurden unter C geschrieben und zusammen 
gelinkt, damit sie auf den jeweiligen Microcontrollern ausführbar sind. 
Die Programme wurden jeweils unter gleichen Bedingungen ausgeführt 
(gleiche Compiler- und Linkereinstellungen, gleicher Speicherbereich).
Als Compiler kamen Keil und Tasking VX Toolset zum Einsatz, als 
Controller u.a, XMC4500 (Infineon) bzw. XC2287 (ebenfalls Infineon). Die 
Laufzeitunterschiede sind deutlich messbar und fallen nicht in den 
Bereich der Messunsicherheiten - gemessen wurde mittels Oszilloskop.

Was könnte die Ursache dafür sein?

Viele Grüße,
Alex

von Peter II (Gast)


Lesenswert?

vergleiche doch einfach mal den ASM code.

Wenn aber ein Modul einen Interrupt nutzt, dann wird es für alle anderen 
natürlich langamer.

von Alexander F. (itfreak12)


Lesenswert?

Der ASM-Code ist identisch in beiden Fällen. Nur die Adressen, auf denen 
die Anweisungen stehen, ändern sich logischerweise.

Das Programm verwendet keine Interrupts, es ist ein rein sequentieller 
Durchlauf ohne Unterbrechungen.

Viele Grüße

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Das könnten Optimierungsunterschiede sein. Sind mehrere Funktionen in 
einer Übersetzungseinheit enthalten, können sie anders optimiert werden, 
als wenn sie in getrennten Übersetzungseinheiten enthalten sind.

Beispielsweise kann sich der Compiler dazu entschließen, eine Funktion 
per Inlining aufzurufen (also den resultierenden Code an die Stelle des 
Aufrufs zu kopieren), das aber setzt naturgemäß voraus, daß der Compiler 
den Code der Funktion kennt, was er nicht tut, wenn der Code der 
Funktion in einer anderen Übersetzungseinheit enthalten ist.

von Alexander F. (itfreak12)


Lesenswert?

Das wäre eine Erklärung - aber das Disassembly ist bis auf die Adressen 
identisch. Somit kann eigentlich nicht einmal Inlining und einmal kein 
Inlining (oder eine ähnliche Optimierung) angewendet worden sein, oder?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Wenn Du den disassemblierten final gelinkten Code miteiander 
vergleichst, und der identisch ist, dann kann es auch keine 
Laufzeitunterschiede geben.

Es sei denn, das Programm wird aus dem RAM ausgeführt, und der µC, auf 
dem das ganze läuft, verwendet unterschiedlich schnelles RAM, wie z.B. 
internes SRAM gegenüber externem (S)DRAM bei manchen ARMen.

Das würde den Unterschied bei unterschiedlichen Adressen erklären.

von Alexander F. (itfreak12)


Lesenswert?

Ja, das ist genau das Mysterium. Die Adressen stammen alle aus dem 
gleichen Speicherbereich, liegen jedoch - je nachdem, was noch 
eingebunden wird - etwas auseinander. Generell habe ich das Programm aus 
dem Flash-ROM ausgeführt, und es müsste auch immer derselbe Flash-ROM 
sein. Deshalb kann ich mir auch keinen Reim darauf machen, wie soetwas 
sein kann.

Ein Detail:

Das Projekt bleibt unangetastet. Wenn eine bestimmte, vom Rest 
unanhängige Funktion ausgeführt werden soll, muss ein Define in einer 
Konfig-Datei gesetzt sein. Es werden also nur Defines auskommentiert 
oder eben nicht. Der Aufruf der Funktion wird durch das Define 
gesteuert. Sonst finden keine Änderungen statt.

Der beschriebene Effekt tritt bei verschiedenen - zwischen den Tests 
immer gleich gehaltenen Einstellungen - auf. Derzeit kann ich dieses 
Verhalten z.B. unter -O0 in Keil µVision reproduzieren. Der 
Laufzeitunterschied beträgt hier aktuell 300ms, auf eine Gesamtlaufzeit 
von etwa 7s, was ja schon erheblich ist. Gemessen wird in 1/100s über 
Oszi, Debugger läuft nicht mit (Hard-Reset und los).

Meine Ideen bisher:

-Whole Program Optimization --> ist laut Compiler-String nicht 
eingeschaltet, aber wer weiß, was der Compiler für generelle Features 
hat?

-near/far Jumps: Aber dann müssten eigentlich andere Sprünge im 
Disassembly verwendet werden, oder?

Ich nehme weitere Vorschläge/Ratschläge/Ideen gern an :-) Habe sowas 
noch nie gesehen.

von Der (Gast)


Lesenswert?

Kannst du das Programm hochladen?
Oder zum Testen Teile des Programms entfernen bis nur noch die 
Funktion(en) da ist(sind), die einen Laufzeitunterschied haben?

Gruß

von Reinhard Kern (Gast)


Lesenswert?

Hallo,

man macht das in C normalerweise ja nicht, aber rein testhalber, 
verschieb mal nur ein Programm das betroffen ist im Speicher (absolut 
adressieren, Null-Blöcke einfügen, es gibt da verschiedene 
Möglichkeiten), um festzustellen, ob schon allein die Verschiebung eine 
Änderung der Ausführung bewirkt.

Gruss Reinhard

von Alexander F. (itfreak12)


Lesenswert?

Das Programm und auch Teile kann ich leider nicht hochladen, da das 
Programm nicht herausgegeben werden soll. Den Rest kann ich erst morgen 
machen.
Danke an alle, die mir bisher geholfen haben.

von Tillomar S. (tillomar)


Lesenswert?

Wenn das Controller mit Zusatzfunktionen für ISO 26262 "Funktionale 
Sicherheit" sind, dann machen die nach dem Reset möglicherweise erst mal 
einen Speichertest. Mißt Du die Laufzeit ab Reset, oder hast Du einen 
speziellen Marker für den Begin der zu messenden Funktion?

So long,
Tillomar

von Alexander F. (itfreak12)


Lesenswert?

Es ist möglich, dass die Controller einen Speichertest machen. Wir 
messen hier aber erst ab einem definierten Punkt nach dem vollständigen 
Init, quasi ab einem Punkt in der main().

@Reinhard Kern:

Das ist ein guter Tipp, ich wollte ohnehin das Programm soweit 
zusammenkürzen, bis ich eine minimale Version habe (wie auch im 
vorherigen Post vorgeschlagen). Dabei könnte ich das gleich mit 
probieren.

Mal noch was anderes:

Wenn der Linker selbst Adressen verteilt, auf denen dann irgendwo im 
gleichen Speicher (gleicher Typ, z.B. das interne Flash-ROM) die 
Funktionen stehen, kann es sein, dass man da ggf. über irgendwelche 
Segmentgrenzen hinweg adressieren muss, und das ganz einfach länger 
dauert? Wenn ja, würde man das anhand der Befehle im Disassembly sehen 
(geänderte Sprungbefehle), oder würde der Controller das 
'stillschweigend' machen? In die Pipeline der Controller können wir ja 
nicht reinschauen...

Vielen Dank für die rege Beteiligung :-)

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Alexander Fischer schrieb:
> ine
> andere Laufzeit erhalte, als wenn ich diese Datei als
> eine von mehreren ausführe
In welchem Bereich? Minuten? Sekunden? Nanosekunden? ... Wieso ist das 
relevant? (Wird ein benötigtes Zeitverhalten nicht mehr eingehalten?)

von Peter II (Gast)


Lesenswert?

Läubi .. schrieb:
> Alexander Fischer schrieb:
>> ine
>> andere Laufzeit erhalte, als wenn ich diese Datei als
>> eine von mehreren ausführe
> In welchem Bereich? Minuten? Sekunden? Nanosekunden? ... Wieso ist das
> relevant? (Wird ein benötigtes Zeitverhalten nicht mehr eingehalten?)

steht alls schon lange da!

von Alexander F. (itfreak12)


Lesenswert?

Das kommt zum großen Teil auf die Gesamtsituation an. Derzeit sind es 
bei einem XMC4500 Testprojekt 0,3s auf insgesamt etwa 7,0s. Es hat aber 
auch schon andere Controller gegeben, bei denen das prozentual noch mehr 
ausmacht.

Es ist halt kein verlässliches Zeitverhalten (ich denke da z.B. an 
Programme, die unter gewissen Echtzeitanforderungen laufen, und wo durch 
Hinzufügen / Entfernen von Code sich die Laufzeit anderer Methoden 
ändert, obwohl die völlig unabhängig arbeiten. Um aber Missverständnisse 
zu vermeiden: wir haben bei den Tests hier noch KEINE Interrupts am 
laufen.)

von Alexander F. (itfreak12)


Lesenswert?

Zusätzliche Erkenntnis:

Es ist sogar so, dass eine nur mit Nops gefüllte Methode die Laufzeit 
der eigentlich zu messenden Methode verändert. Dadurch, dass damit 
offenbar mehr Code erzeugt wird, muss sich irgendwas im Speicher ja 
verschieben, und das scheint die Laufzeit zu beeinflussen. Es ist sogar 
so, dass wenn die Nop-Methode mehrfach aufgerufen wird, mal die Laufzeit 
der Testmethode steigt, und mal sinkt, je nachdem, wie oft man die 
Nop-Methode davor aufruft. Wir messen natürlich nur die Laufzeit um die 
Testmethode, die Nops sind außen vor...

von Peter II (Gast)


Lesenswert?

Alexander Fischer schrieb:
> Es ist sogar so, dass eine nur mit Nops gefüllte Methode die Laufzeit
> der eigentlich zu messenden Methode verändert.

gibt es nicht soetwas wie ein simualor? Damit sollte man doch genau 
erkennen wo die zeit vergeht.

von oszi40 (Gast)


Lesenswert?

Es ist auch ein zeitlicher Unterschied ob man ganze Speicherblöcke 
transportiert oder irgendwo einzelne Speicherzellen befehlsweise holen 
muß.

von Stefan (Gast)


Lesenswert?

> kann es sein, dass man da ggf. über irgendwelche Segmentgrenzen hinweg 
adressieren muss, und das ganz einfach länger dauert.

Kann sein. Ich kenne diesem µC nicht gut genug, um diese Frage mit 
Sicherheit zu beantworten.

Du hast ja schon geprüft, dass der Assembler Code gleich ist. Es kann 
also nicht an Unterschieden zwischen Long-Jump und Short-Jump liegen.

Jedoch gibt es eventuell Befehle, die je nach Parameter-Wert 
unterschiedlich lange brauchen (wie man es z.B. von Divisionen kennt) 
und bei Deinem Fall eine Rolle spielen.

von Vlad T. (vlad_tepesch)


Lesenswert?

unterscheidet sich der Speichertyp?
Level1 / Level2 Cache?
landen durch die anderen Adresse die Daten in ungecachten Speicher?

von Arc N. (arc)


Lesenswert?

Doch unterschiedliche Speicherbereiche?

Im RM zu den XMC4x00 sind zwei Speicherbereiche aufgeführt die zwar auf 
den selben physischen Speicher gemappt sind, aber einmal gecached das 
andere mal ungecached.
8.4.3
PMU0 Program Flash Bank non-cached
PMU0 Program Flash Bank cached space
(different address space for the same physical memory, mapped in the 
non-
cached address space)
8.4.4
The PMU allows 4x64-bit burst accesses to the cached address space and 
single 32-bit read accesses to the non-cached address space of the 
PFLASH.
The Prefetch generates the 4x64-bit bursts for code and data fetches 
from the cached address range in order to fill one cache line or the 
data buffer respectively. Data reads from the non-cached address range 
are performed with single 32-bit transfers

von Alexander F. (itfreak12)


Lesenswert?

Nach langem Suchen scheinen zumindest einige Verdächtige ausgemacht:

Beim XMC4500 scheint es Unterschiede zwischen Keil µVision 4.60 und 
4.70a zu geben, derart, dass unter 4.70a der Effekt kaum nachweisbar 
ist, umso deutlicher aber in Version 4.60. In den Release-Notes werden 
diverse Compiler-Probleme, im Zusammenhang mit falschen Condition-Flags 
genannt, die ab 4.70 behoben sein sollen. Daher könnte dies ein Grund 
für die Laufzeitunterschiede sein. Zusätzlich scheint auch der Cache 
eine Rolle zu spielen, wenn man den Code im Cached Flash ausführt (wir 
haben sowohl cached als auch non-cached Flash untersucht). Man kann 
durchaus seine Wirkung messen. Zusätzlich kommt - vor allem bei 
non-Cached Flash - die Wirkung des Instruction Prefetch zum Tragen. Der 
Effekt ist messbar, verglichen mit den Laufzeiteffekten bei Version 4.60 
aber geringer ausgeprägt.

Bei ähnlichen Beobachtungen bei einem XC2000 und Tasking VX Toolset habe 
ich mich an den Tasking-Support gewandt. Eine Antwort steht noch aus, 
jedoch scheint der Linker auch einen Einfluss zu haben. Streicht dieser 
z.B. nicht benötigten Code und Daten raus, ändert sich auch (in geringen 
Maßen) die Laufzeit.

Soviel erstmal als Update zu der Problematik. Vielen Dank nochmal für 
die vielen Beiträge. Weitere Hinweise sind natürlich stets willkommen 
:-)

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.