Forum: Compiler & IDEs User Sections GCC


von clonephone82 (Gast)


Lesenswert?

Hallo Zusammen,

Bei einem Projekt mit einem STM32 brauche ich zwischen dem Bootloader 
und der Applikation einen Shared Memory Bereich - für Datenaustausch. 
Jetzt funktionierte das bisher soweit, aber letztens musste ich weil ich 
keinen Platz mehr im Bootloader hatte, die Optimierung einschalten. Also 
Wechsel von -O0 auf -O1 das war alles.

Jetzt habe ich das Problem, dass dieser Shared- Memory nicht mehr so 
funktioniert wie er ohne Optimierung funktioniert.

Umsetzung:

Ich habe sowohl beim Bootloader und bei der Applikation das Linker File 
um den folgenden Eintrag ergänzt.
1
    .noinit (NOLOAD) : ALIGN(4)
2
    {
3
      _noinit = .;
4
5
      *(.noinit .noinit.*)
6
7
      . = ALIGN(4) ;
8
      _end_noinit = .;
9
    } > SRAM

Beim Linken verwende ich dann bei beiden
1
--section-start=.sysinfo=0x20002800

Für mich sieht es so aus als wie diese NOLOAD nicht mehr funktioniert.
Hat jemand vielleicht eine Idee - wie das ist mit User Sections?

Brauch eine UserSection -> wo ich die Adresse zuweisen kann.
Darf nicht initialisiert werden.
Sollte egal, welche Optimierung eingeschaltet wird,  immer 
funktionieren.

Vielen Dank
sg
mathias

: Verschoben durch User
von Jim M. (turboj)


Lesenswert?

Ich glaube eher dass der Fehler in Deinem Source Code zu suchen ist. 
Zeig den doch mal.

von Ralf (Gast)


Lesenswert?

Hi Mathias,

bin selbst grad am Einlernen mit GCC, aber mir fiel da grad spontan 
'remove unused sections' ein. Kann es etwas damit zu tun haben?

Ralf

von I <3 makefiles (Gast)


Lesenswert?

PRINZIP:
die ShMem Datendefinitionen und die paar wenigen Routinen um darauf 
zuzugreifen gehören sowohl f. BootLdr als auch f. Applikation 
IDENTISCH kompiliert, also mit IDENTISCHEN Compileroptionen (falls 
überhaupt 2x und nicht nur 1 einziges Mal kompiliert)

Im BootLdr duerften diese nur einen sehr kleinen Platzanteil ausmachen, 
sodass nur diese -O0 geniessen können während der überwiegende Rest des 
BootLdr -O1 oder schärfer unterliegt.

(heisst auch "separate compilation")


UMSETZUNG:
Also: im Makefile (oder wo auch immer in der Projektverwaltung anstelle) 
fuer genau  diese paar Sourcedateien die paar spezifischen 
Compileroptionen explizit setzen (gem. Bsp. -O0 anstatt -O1) die 
Projektallgemeinen blind verwenden.

Ist das Prj./die Teilprj. korrekt Modularisiert -inkl. Makefile(s) 
Hierarchie- liegen diese paar Sourcedateien in einem eigenen 
Unterverzeichnis mit eigenem (Teil-)Makefile -- eben genau damit das 
Handling des ShMem in separaten Binaries (BootLdr, Anwendung) 
IDENTISCH ausfallen.

von Peter II (Gast)


Lesenswert?

kann es sein das durch die Optimierung die Werte gar nicht in dem Ram 
geschrieben werden? Hast du die Variablen die in der Section liegen auch 
als volatile gekennzeichnet?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Vielleicht orientierst du dich am avr-gcc, dirt funktioniert .noinit 
nämlich.  Hier ein Beispiel aus ./avr/lib/ldscripts:
1
...
2
MEMORY
3
{
4
  text   (rx)   : ORIGIN = 0, LENGTH = 128K
5
  data   (rw!x) : ORIGIN = 0x800060, LENGTH = 0xffa0
6
  ...
7
}
8
SECTIONS
9
{
10
  ...
11
  .text   :
12
  {
13
    ...
14
  }  > text
15
  .data    : AT (ADDR (.text) + SIZEOF (.text))
16
  {
17
     PROVIDE (__data_start = .) ;
18
     ...
19
     PROVIDE (__data_end = .) ;
20
  }  > data
21
  .bss   : AT (ADDR (.bss))
22
  {
23
     PROVIDE (__bss_start = .) ;
24
    *(.bss)
25
    *(.bss*)
26
    *(COMMON)
27
     PROVIDE (__bss_end = .) ;
28
  }  > data
29
   __data_load_start = LOADADDR(.data);
30
   __data_load_end = __data_load_start + SIZEOF(.data);
31
  /* Global data not cleared after reset.  */
32
  .noinit  :
33
  {
34
     PROVIDE (__noinit_start = .) ;
35
    *(.noinit*)
36
     PROVIDE (__noinit_end = .) ;
37
     _end = . ;
38
     PROVIDE (__heap_start = .) ;
39
  }  > data
40
  ...
41
}
Dass .noinit nicht initialisiert wird ist dann Teil des Start-Codes.

Beachte dass da kein NOLOAD bei .noinit steht! Den Typ der 
Output-Section bestimmt ld aus den Input-Sections, und .noinit hat das 
"a" Flag gesetzt. Die Section belegt ja Platz auf dem Target.

von S. R. (svenska)


Lesenswert?

> PRINZIP:
> die ShMem Datendefinitionen und die paar wenigen Routinen um darauf
> zuzugreifen gehören sowohl f. BootLdr als auch f. Applikation
> IDENTISCH kompiliert, also mit IDENTISCHEN Compileroptionen (falls
> überhaupt 2x und nicht nur 1 einziges Mal kompiliert)

Das ist grober Unfug. Wichtig ist, dass das Speicherlayout in beiden 
Systemen gleich ist, mehr nicht.

Also: Du definierst eine struct, die du mit __attribute__((aligned(x))) 
und __attribute__((packed)) auf ein festes Speicherlayout zwingst. Diese 
Definition muss in beiden Systemen gleich sein (z.B. gemeinsam genutzter 
Header).

Im Code selbst deklarierst du eine globale Variable von diesem Typ an 
und legst sie als einzige Variable in diese Section, mit 
__attribute__((section(x))), denn dann liegt sie definiert am Anfang der 
Section. Sinnvollerweise machst du diese Variable auch volatile, falls 
beide Systeme gleichzeitig darauf zugreifen müssen.

Fertig. Der Compiler macht den Rest. Das funktioniert auch über 
Architektur- und Compilergrenzen hinweg, solange die Endianness stimmt.

von clonephone82 (Gast)


Lesenswert?

Hallo Vielen Dank für die Rückmeldung.

Habe viele Sachen die Ihr hier gesagt habt gemacht bzw. werde ich am 
Montag dann noch ausprobieren.

@S.R. habe ich natürlich genau so gemacht. Der Bootloader Funktioniert 
ja auch inklusive Shared Memory aber nur wenn ich den Loader mit -O0 
compiliere. Sonst funktioniert der noinit nicht richtig. Es wird 
sozusagen immer gelöschen bei -O1 warum auch immmer. Sobald ich hier 
etwas mehr sagen kanns schreibe ich wieder.

Von wo habe ich die Ideen

Not init:
http://mcuoneclipse.com/2014/04/19/gnu-linker-can-you-not-initialize-my-variable/

Placing Vars:
http://www.avrfreaks.net/forum/tutgccadding-crc-and-app-length-hex-files
http://mcuoneclipse.com/2012/11/01/defining-variables-at-absolute-addresses-with-gcc/

sg

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


Lesenswert?

volatile vergessen?

von I <3 makefiles (Gast)


Lesenswert?

ok, ich hab über's Ziel hinaus geschossen.

Ich habe mich vom Begriff "Shared Memory" verleiten lassen.

Shared Memory trifft im engeren Sinne hier ja insofern nicht zu, dass 
BootLdr und Applikation zeitlich nacheinander laufen (nicht 
gleichzeitig).

Ich arbeitete eben länger auf modularen MultiCPU Systeme (mind. 1 CPU 
pro Steckkarte), welche via ShMem/VME-Bus kommunizieren. Hier ist 
natürlich arbitrierender Code drumrum nötig.

Beim sequentiellen BootLdr<->Applikation Ablauf genügen natürlich 
saubere Datendefinitionen.

Die Ergänzung m. Endian-awareness gefällt mir auch.

von clonephone82 (Gast)


Lesenswert?

Hat jemand noch eine Idee - hab das Problem noch nicht gelöst bekommen 
volatile hin oder her. Komme jetzt mit dem Platz ohne Optimierung nicht 
mehr aus.

sg
Danke.

von Markus F. (mfro)


Lesenswert?

clonephone82 schrieb:
> volatile hin oder her

Hast Du jetzt volatile für die zu übergebenden Variablen drin oder 
nicht?

Mapfile schon mal angeschaut?

Code geposted?

Dass es am Linkerscript liegt, glaubt nämlich hier ausser dir 
wahrscheinlich keiner (mehr).

von clonephone82 (Gast)


Lesenswert?

War wirklich ein Programmier fehler - sorry.
Placing funktioniert wie in den Links beschrieben.

Danke für die Hinweise!

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.