Forum: Compiler & IDEs STM32F4 I-Bus


von Little B. (lil-b)


Lesenswert?

Hallo Community!

Seit ich mich tiefer mit dem STM32F4 beschäftige und auch seine 
Speicher-Architektur im Detail verstehen will, interessiert mich vor 
allem eine Frage:

Wann wird der I-Bus verwendet?
Sind die vorgegebenen Linkerskripte von Keil/Atollic/etc korrekt?

Diese Frage ist hier auch schon mal aufgetaucht, und die Antwort lautete 
damals:
"Das passt so. Das Programm wird an 0x08000000 gelinkt und abgelegt, 
denn da ist das Flash."
Aber ist der ARM-Core intelligent genug, um zu wissen, dass er diese 
Adressen über den I-Bus erreichen kann?

Ich habe soeben mal gemessen. Coremark, wie man es unter 
http://www.eembc.org/coremark/download.php herunterladen kann. 
Minimalste Anpassungen für die Clock, Printf und Timer. Alles ins RAM 
gelinkt, um Flash-Latenzen außen vor zu lassen.

3000 Iterationen im Performance Run benötigen dann 52,741 Sekunden

Dann habe ich das Linkerskript modifiziert:
- Memory section IBUS erstellt
- .isr_vector und .text in den IBUS gelinkt, aber mit Loadaddress im RAM

das sieht dann so aus:
1
MEMORY
2
{
3
  IBUS (x)    :  ORIGIN = 0x00000000, LENGTH = 1024k
4
  FLASH (rx)    :  ORIGIN = 0x08000000, LENGTH = 1024k
5
  RAM (xrw)    :  ORIGIN = 0x20000000, LENGTH = 128K
6
  MEMORY_B1 (rx)  :  ORIGIN = 0x60000000, LENGTH = 0K  /* FSMC address space */
7
  CCMRAM (rw)    :  ORIGIN = 0x10000000, LENGTH = 64K  /* only accessible by CPU */
8
}
9
10
/* Define output sections */
11
SECTIONS
12
{
13
  /* The startup code goes first into FLASH */
14
  .isr_vector :
15
  {
16
    . = ALIGN(4);
17
    KEEP(*(.isr_vector)) /* Startup code */
18
    . = ALIGN(4);
19
  } >IBUS AT> RAM
20
  
21
  .text :
22
  {
23
    /* put interrupt service routines first into flash */
24
    *(.*_Handler)
25
    *(.*_IRQHandler)
26
    
27
    /* all program code goes here */
28
    *(.text)           /* .text sections (code) */
29
    *(.text*)          /* .text* sections (code) */
30
    *(.glue_7)         /* glue arm to thumb code */
31
    *(.glue_7t)        /* glue thumb to arm code */
32
    *(.eh_frame)
33
    
34
    KEEP (*(.init))
35
    KEEP (*(.fini))
36
    
37
    . = ALIGN(4);
38
    _etext = .;        /* define a global symbols at end of code */
39
  } >IBUS AT> RAM
40
{...}

Neu compiliert und gelinkt habe ich den selben Test ablaufen lassen. Und 
nun braucht dieser nur noch 37,159 Sekunden.

Das sind fast *30%* weniger Zeit! Fast *40%* Leistungsgewinn!

Die Linkerskripte sind also nicht auf die Hardware optimiert.
Leider findet man zu diesem "Feature" auch absolut keine Informationen 
im Internet. Selbst STM sagt nur, dass es den IBus gibt, aber nicht, wie 
man den richtig verwendet.

~Lil B

von Dr. Sommer (Gast)


Lesenswert?

Little B. schrieb:
> Minimalste Anpassungen für die Clock, Printf und Timer. Alles ins RAM
> gelinkt, um Flash-Latenzen außen vor zu lassen.
>
> 3000 Iterationen im Performance Run benötigen dann 52,741 Sekunden

Du vergleichst also Flash mit RAM. Vergleiche doch mal deine "IBUS" 
section an adresse 0 mit ausführung ganz normal aus dem Flash (also 
0x08000000...).

von Little B. (lil-b)


Lesenswert?

Nein, ich vergleiche RAM über 0x20000000 mit RAM über 0x00000000

von Dr. Sommer (Gast)


Lesenswert?

Little B. schrieb:
> Nein, ich vergleiche RAM über 0x20000000 mit RAM über 0x00000000

Achso, mich hat verwirrt dass du nirgendwo erwähnst, dass du den RAM an 
Adresse 0x00 umgemappt hast, denn normalerweise ist da ja auch der Flash 
zu finden ;-)

Interessant wäre dann noch das gleiche nur mit Flash, also Flash an 
0x08000000 vs. Flash an 0x00, denn das ist ja der "normale" 
Anwendungsfall, für den auch die normalen Linkerscripte sind...

von Little B. (lil-b)


Lesenswert?

Dr. Sommer schrieb:
> Interessant wäre dann noch das gleiche nur mit Flash, also Flash an
> 0x08000000 vs. Flash an 0x00, denn das ist ja der "normale"
> Anwendungsfall, für den auch die normalen Linkerscripte sind...

Das habe ich just getan.
Hier scheint es jedoch egal zu sein, wohin man linkt.
Ob von 0x00 oder von 0x08000000 ergibt beides (der selbe test wie oben) 
37,052 Sekunden.

...jetzt bin ich verwirrt und enttäuscht...

von Tassilo H. (tassilo_h)


Lesenswert?

Das ist "halbwegs" dokumentiert, wenn man sich in der Doku 
zurechtgefunden hat. Im Adressbereich 0x00000000 bis 0x1FFFFFFF werden 
Instruktionen über den I-Bus geholt, wohingegen im Bereich ab 0x20000000 
Instruktionen über den geteilten D-Bus geholt werden.

Bei Flash ist es egal, ob man für Startadresse 0 oder 0x08000000 linkt, 
da beide Adressbereiche, in denen das Flash eingeblendet werden kann, im 
Codebereich liegen. Beim SRAM ist es nicht egal, denn wenn man für 
Startadresse 0 linkt, ist es schneller, als wenn man für 0x20000000 
linkt (spätestens nach dem ersten Sprung nach dem Resetvektor erfolgen 
die Codezugriffe dann über Adressen 0x20....
Siehe Reference Manual Seite 69
http://www.st.com/web/en/resource/technical/document/reference_manual/DM00031020.pdf

Genauso ärgerlich ist, daß kaum ein Linkerscript, das durchs Netz oder 
bei den diversen IDEs dabei ist, das core-coupled SRAM vernünftig nutzt. 
Wenn man zwei DMAs am laufen hat (Ethernet, SD-Card), macht es gefühlte 
30-50% aus, wenn der Stack im CCM und nicht im normalen SRAM liegt.

von Little B. (lil-b)


Lesenswert?

Tassilo H. schrieb:
> Das ist "halbwegs" dokumentiert, wenn man sich in der Doku
> zurechtgefunden hat. Im Adressbereich 0x00000000 bis 0x1FFFFFFF werden
> Instruktionen über den I-Bus geholt, wohingegen im Bereich ab 0x20000000
> Instruktionen über den geteilten D-Bus geholt werden.

Wieder was gelernt!

Ich bin von der Tabelle auf Seite 71 in diesem Reference Manual 
ausgegangen, wo ein Adressbereich von 1MB angegeben ist. Dass der IBus 
aber 512 MB adressieren kann, hab ich bisher noch nicht gelesen.

Also ist meine obige Information nur relevant, wenn man vom SRAM oder 
aus dem FSMC das Programm ausführt.

von Stefan (Gast)


Lesenswert?

Tassilo H. schrieb:
> Genauso ärgerlich ist, daß kaum ein Linkerscript, das durchs Netz oder
> bei den diversen IDEs dabei ist, das core-coupled SRAM vernünftig nutzt.
> Wenn man zwei DMAs am laufen hat (Ethernet, SD-Card), macht es gefühlte
> 30-50% aus, wenn der Stack im CCM und nicht im normalen SRAM liegt.

Was ist hierbei der Leistungsgewinn wenn der Stack im CCM liegt ?
DMA Zugriffe auf dem CCM funktionieren ja nicht wenn ich das richtig 
verstanden habe.

von Tassilo H. (tassilo_h)


Lesenswert?

Stefan schrieb:
> Was ist hierbei der Leistungsgewinn wenn der Stack im CCM liegt ?
> DMA Zugriffe auf dem CCM funktionieren ja nicht wenn ich das richtig
> verstanden habe.

Na ja, man legt die DMA-Buffer (z.B. Buffer für SD-Card und Ethernet) 
ins normale SRAM. Die muß der CPU-Core ja meist nicht komplett selber 
verarbeiten. Wenn man Ethernet und SD-Card mit hoher Datenrate laufen 
läßt, ist die Busauslastung damit schon nennenswert, d.h. die 
Wahrscheinlichkeit ist hoch, daß ein Zugriff warten muß.

Alle lokalen Variablen liegen auf dem Stack, legt man den (und ggf. auch 
globale Buffer, auf die DMA nicht zugreifen muß) ins CCM, muß der Core 
viel seltener auf einen RAM-Zugriff warten (meist gibt es ja noch mehr 
zu tun als nur SD-Karte und Ethernet anzusteuern).

Das ganze hat zugegebenermaßen Fallstricke und deshalb ist es vmtl. in 
den Tutorials meist nicht drin: Wenn man z.B. Elm CHan's FatFS mit der 
ST-Beispielimplementierung für den SD-Zugriff einfach ungesehen 
übernimmt, geht das schief, wenn man mal 512 Bytes oder mehr auf einmal 
aus einer lokalen (Stack-)Variable an die Schreibfunktion übergibt: Die 
SD-Card-Library versucht, den Sektorbuffer zu umgehen, wenn möglich, und 
wird versuchen, die Daten direkt von der Quelle zu schreiben. Das klappt 
dann nicht. Andererseits ist das nur einer von mehreren Fallstricken, 
die sowieso schon bei der DMA-Verwendung lauern (Alignment der 
Datenbuffer, DMA kann ggf. keine 4k-Adressgrenze queren, irgendwas war 
da).

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.