Forum: Mikrocontroller und Digitale Elektronik STM32F767 GPIO Geschwindigkeit hängt an Debug/Release


von Noob A. (strippenzieher)


Lesenswert?

Guten Tag,

ich lerne gerade den STM32F767 kennen (Nucleo-board) und hab mir gerade 
'nen Wolf gesucht weil ich die Pins nicht schneller als 12,7 MHz toggeln 
konnte

Den Pin bediene ich mit:
1
GPIOD->BSRR = 0x04000000U;
2
GPIOD->BSRR = 0x00000400U;

Irgendwann hab ich dann, warum auch immer, mal beim kompilieren von 
Debug auf Release umgestellt. Also die Optimization von -O0 auf -O3.

Und siehe da die im Datenblatt angepriesenen 108MHz sind da :)

"Again what learned" sagt der Franzose ;)


Was mir jetzt noch unklar ist: wieso ich ziemlich präzise alle ms eine 
Unterbrechung von ca 430ns habe

von Dr. Sommer (Gast)


Lesenswert?

Bob A. schrieb:
> Was mir jetzt noch unklar ist: wieso ich ziemlich präzise alle ms eine
> Unterbrechung von ca 430ns habe

SysTick Timer Interrupt. Ohne Optimierung übersetzt der Compiler 
ziemlich "dumm", sodass selbst so simple Register-Zugriffe und die 
vermutlich drum herum gebaute Schleife um ein Vielfaches langsamer 
werden.

von georg (Gast)


Lesenswert?

Bob A. schrieb:
> mal beim kompilieren von
> Debug auf Release umgestellt

Das ist kein Wunder. In Debug-Versionen muss zusätzlicher Code eingefügt 
werden (z.B. zur Anzeige von Zeilennummern im Sourcecode), und der muss 
natürlich auch ausgeführt werden. Und einige Optimierungen werden nicht 
angewendet, sonst erlebt man beim Debuggen komische Sachen wie fehlende 
Codestücke.

Georg

von Stefan F. (Gast)


Lesenswert?

Die Zeilennummern stehen nicht direkt im Code drin. Aber wenn man den 
Optimizer frei arbeiten lässt, strukturiert er das Programm bis zur 
Unkenntlichkeit um, so dass der Debugger Probleme bekommt, den 
zugehörigen C-Quelltext wieder zu finden.

von Dr. Sommer (Gast)


Lesenswert?

Man kann auch optimierten Code mit Debug-Informationen kompilieren. Der 
Code selbst wird dadurch nicht beeinflusst, der Controller merkt keinen 
Unterschied zwischen "Mit Debug Info" und "Ohne Debug Info". Es wird 
lediglich die ELF Datei größer. Daher kann man das meist auch völlig 
bedenkenlos machen. Die zusätzlichen Debug-Informationen in der ELF 
Datei werden vom Debugger ausgewertet (typischerweise GDB) um z.B. zur 
Adressen Code-Stellen zuzuordnen. Wie schon gesagt ist diese Zuordnung 
bei eingeschalteter Optimierung etwas durcheinander was das Debugging 
erschwert. Es ist aber manchmal unumgänglich, wenn ein Problem nur bei 
eingeschalteter Optimierung auftritt, oder der Controller schlicht nicht 
genug Flash für die unoptimierte Version hat.

von Stefan F. (Gast)


Lesenswert?

Der arm-gcc hat dazu die Kompromiss-Option: -Og

Damit optimiert er so viel wie möglich, ohne den Debugger lahm zu legen.

von Dr. Sommer (Gast)


Lesenswert?

Wobei "lahm legen" übertrieben ist. Auch bei voller Optimierung 
funktioniert das Debugging an sich; die Abfolge der Anweisungen 
innerhalb von Funktionen gerät durcheinander und lokale Variablen können 
verschwinden/sich anders verhalten. Mit etwas Fummelei kann man dem 
Programmablauf aber schon folgen.

von Jim M. (turboj)


Lesenswert?

Dr. Sommer schrieb:
> Wobei "lahm legen" übertrieben ist. Auch bei voller Optimierung
> funktioniert das Debugging an sich;

.. wenn man nicht die Debug Symbole ausgeschaltet hat. Das machen einige 
IDEs als Vorgabe im Release Mode. Abhilfe: Wieder einschalten, sowohl 
beim Compiler als auch beim Linker.

Weiterhin ist es eine große Hilfe wenn man das Disassembly wenigstens 
lesen kann.
Ein Vergleich der Assembler Instruktionen und dem zugehörigen C Code 
ergibt gelegentlich die Einsicht dass der Compiler ein paar Dinge findet 
die man flashc programmiert hat.

von Dr. Sommer (Gast)


Lesenswert?

Jim M. schrieb:
> . Das machen einige IDEs als Vorgabe im Release Mode

Bloß warum... Die 1MB hat man auf seiner Festplatte ja noch. Das landet 
ja wie gesagt nicht auf dem Controller...

Jim M. schrieb:
> Weiterhin ist es eine große Hilfe wenn man das Disassembly wenigstens
> lesen kann

Das sowieso ja... Wobei der optimierte Code mMn besser lesbar ist.

von tgdfgdf (Gast)


Lesenswert?

TIP: der F7 hat ITCM Speicher
mach dich schlau und lege die ISR und zeitkritische funktionen in diesem 
Bereich ab

zugriffe aus dem flash haben bei den 216Mhz 7 Waitstates.
bei funktionen aus dem ITCM: 0

von Noob A. (strippenzieher)


Lesenswert?

Dr. Sommer schrieb:
> Bob A. schrieb:
>> Was mir jetzt noch unklar ist: wieso ich ziemlich präzise alle ms eine
>> Unterbrechung von ca 430ns habe
>
> SysTick Timer Interrupt. Ohne Optimierung übersetzt der Compiler
> ziemlich "dumm", sodass selbst so simple Register-Zugriffe und die
> vermutlich drum herum gebaute Schleife um ein Vielfaches langsamer
> werden.

Die Pause alle ms hab ich auch mit -O3...
Wo kommt denn der SysTick her?

von Noob A. (strippenzieher)


Lesenswert?

tgdfgdf schrieb:
> TIP: der F7 hat ITCM Speicher
> mach dich schlau und lege die ISR und zeitkritische funktionen in diesem
> Bereich ab
>
> zugriffe aus dem flash haben bei den 216Mhz 7 Waitstates.
> bei funktionen aus dem ITCM: 0

Vielen Dank für den Tipp!
Bislang denke ich dass es auch aus dem Flash raus schnell genug ist, 
aber sowas im Hinterstübchen zu haben ist Gold wert :)

von Dr. Sommer (Gast)


Lesenswert?

Bob A. schrieb:
> Wo kommt denn der SysTick her?

Die HAL definiert den und braucht den IIRC auch. Der wird natürlich 
nicht bei -O3 wegoptimiert, denn das ist ja gewünschte Funktionalität! 
Wenn dich diese Unterbrechung stört, solltest du dein Konzept 
überdenken.  Pins mit 108MHz in Software togglen klingt nicht besonders 
sinnvoll.

von Noob A. (strippenzieher)


Lesenswert?

Und vielen Dank an alle die beim Thema debug / Optimierer für beseres 
Verständnis gesorgt haben!
Sehr gut zu wissen, und -Og bringt noch einen ordentlichen Schub, da 
komm ich immerhin auf 21MHz.
Das könnte für das Projekt ausreichen falls doch mal parallel am Oszi 
und im Quelltext debugged wird!

von Noob A. (strippenzieher)


Lesenswert?

Dr. Sommer schrieb:
> Bob A. schrieb:
>> Wo kommt denn der SysTick her?
>
> Die HAL definiert den und braucht den IIRC auch. Der wird natürlich
> nicht bei -O3 wegoptimiert, denn das ist ja gewünschte Funktionalität!
> Wenn dich diese Unterbrechung stört, solltest du dein Konzept
> überdenken.  Pins mit 108MHz in Software togglen klingt nicht besonders
> sinnvoll.

Ist es ja auch nicht, aber diese kleine Experimentchen helfen mir beim 
Kennenlernen und Verstehen.
Die mit -O0 gemessenen 12MHz waren aber evtl etwas lahm - und wenn der 
µC 108MHz können sollte ist es offensichtlich das man etwas falsch 
gemacht hat ;)

Ob's stört muss sich herausstellen, denke aber bereits zum jetzigen 
Zeitpunkt ob ich nicht auf die HAL verzichten sollte. Aber es ist nunmal 
sooo bequem ;-)

von gdfgsdgsg (Gast)


Lesenswert?

dann pack den M7 mal richtig voll .. ^^
die Speicherbereiche sind auch sehr witzig.

bei mir sind es
16K ITCM ( für funktionen )
224K SRAM1 ( allgemeinkram )
16K SRAM2 ( für ethernet )
64k DTCM  ( für schnelle sachen , RTOS stack )

problem ist da  das originale linkerfile...

der packt den Stack ans ende vom "RAM ( 320k )"  was am ende des SRAM2 
ist
Der ist langsamer und ist cacheable was irgendwann beim RTOS schonmal 
für verwirrung sorgt ^^

Wenn man  diverse blöcke belegt und er kommt irgendwann über die grenze 
der  ersten 64k( was DTCM ist ) und will in den SRAM1  wirds auch 
witzig.

Die DMA geschichte funktioniert nur zuverlässig aus SRAM1 oder SRAM2

Wenn man dann sich wundert warum das Gerät am anfang bei funktion X so 
schnell war und nun plötzlich langsamer läuft ... hat das 2 ursachen:

RAM bereiche im .map irgendwo anders
Der jump im flash ist größer und er muss den ART komplett umladen


Der M7 hat mich schon so manchen nerv gekostet ^^
Aber er ist gut.

von Johnny B. (johnnyb)


Lesenswert?

Ich nutze normalerweise nur noch folgende Optimierungsoptionen beim GCC:

Debug
-Og (Code wird optimiert, kann aber dennoch gedebuggt werden)

Release
-Os (Kleine Grösse aber dennoch normalerweise schnellerer Code als bei 
-O2)

Hier eine kleine Abhandlung dazu, passend zum Cortex-M / STM32 und GCC:
http://blog.atollic.com/optimizing-code-size-with-the-gnu-gcc-compiler-for-stm32-and-other-arm-cortex-m-targets

von Christopher J. (christopher_j23)


Lesenswert?

Johnny B. schrieb:
> Ich nutze normalerweise nur noch folgende Optimierungsoptionen beim GCC:
>
> Debug
> -Og (Code wird optimiert, kann aber dennoch gedebuggt werden)
>
> Release
> -Os (Kleine Grösse aber dennoch normalerweise schnellerer Code als bei
> -O2)

Der Witz ist ja, das -Os sämtliche Optimierungen von -O2 beinhaltet, 
außer jenen die zusätzlichen Speicherplatz kosten. Auf Grund der 
Waitstates ist aber kompakterer Code häufig auch schneller. -O2 und -Os 
geben sich aber meistens nicht so viel, weder beim Platz noch bei der 
Geschwindigkeit. Bei -O3 sieht die Sache schon ganz anders aus. Da 
werden dann eben auch mal Schleifen ausgerollt und ein dämliches delay() 
müllt den Flash mit sinnlosen NOPs voll. -O3 macht, gerade wegen der 
Waitstates, auf Cortex-M nur sehr selten Sinn. Es erzeugt eigentlich 
immer größeren Code als -O2 und am Ende ist der dann oft sogar doch noch 
langsamer. Für ausgewählte, zeitkritische Funktionen mag -O3 aber 
mittels Compilerdirektive trotzdem Sinn machen.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Oder die Compilerdirektive kommt fors die nop Delayschleife ;)

Die Flash Waitstates werdem ja bei immer mehr ARM SoCs durch mini Caches 
am Flash wegabstrahiert.
Da werden dann 128Bit aus dem Flash geladen und dann liegen die da bis 
alle 16Bit Thumbs abgeholt wurden (manchmal auch 32Bit).
Zudem bemerken diese Caches wann sie drohen leerzulaufen und laden weder 
128Bit nach. Da bekommt man die Waitstates also erst bei sprüngen wider 
zu sehen.

Daher ist das loop unrolling bei dieser Art Cache eigentlich von 
Vorteil?

von Dr. Sommer (Gast)


Lesenswert?

Mw E. schrieb:
> Daher ist das loop unrolling bei dieser Art Cache eigentlich von
> Vorteil?

Na eben nicht! Bei einer normalen Schleife passt vielleicht der ganze 
Code in den Cache, so kann die Schleife im günstigsten Fall ganz ohne 
Flash-Zugriff laufen. Eine ausgerollte Schleife passt ggf. eher nicht 
hinein und erfordert mehr Flash-Zugriffe. Sprünge kosten aber auch Zeit, 
die Prozessoren mit Branch Prediction (Cortex-M7!) reduzieren können. 
Letztlich hängt es vom Einzelfall ab und muss individuell gemessen 
werden.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Das muss dann aber eine kleine Schleife sein, denn 129/16 sind 8 befehle 
Maximum. (bei den STM32F4 zB).

Dr. Sommer schrieb:
> Letztlich hängt es vom Einzelfall ab und muss individuell gemessen
> werden.
Ja da ist das Problem ;)

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.