Hallo,
ich habe eine neue Entwicklungsumgebung für meinen STM32F4107ZG
eingerichtet.
Die Entscheidung ist auf Em::Blocks (mit ARM GCC Compiler) gefallen.
Soweit läuft alles top ;).
An meinem STM32F4107ZG ist ein Externes RAM angeschlossen (ERAM1),
woraus im LinkerSkript der folgende Memory Aufbau resultiert:
------------------------------------------------------------------------
-
MEMORY
{
IROM1 (RX) : ORIGIN = 0x08000000, LENGTH = 0x00100000
IRAM2 (RW) : ORIGIN = 0x10000000, LENGTH = 0x00010000
IRAM1 (XRW) : ORIGIN = 0x20000000, LENGTH = 0x00020000
ERAM1 (RW) : ORIGIN = 0x60000000, LENGTH = 0x00080000
}
...
.bss :
{
_sbss = .; /* define a global symbol at bss start */
_bss_start_ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
_bss_end_ = _ebss;
} >IRAM1
...
------------------------------------------------------------------------
-
Jetzt ist meine .bss-Sektion so groß das sie in keine der RAMs passt.
Ich will dem LinkerSkript gerne folgendes sagen:
"Schreibe die .bss-Sektion erstmal in IRAM1 bis es voll ist, dann
schreibe weiter in IRAM2 bis es voll ist und dann weiter in ERAM1."
Ich will sozusagen die RAMs aneinander hängen.
Ist das möglich?
Wenn ja, wie?
Viele Grüße
crozeg
.
Hi,
so weit ich wieß geht das so nicht du wirst deine Variablen auf mehrere
bss sections aufteilen müssen. Dann kannst du eine in jedem Ram anlegen.
Gruß
Tec
Hallo,
Schonmal danke für die schnelle Antwort.
Ich bin noch neu in LinkerScripting.
Kannst du mir verraten wie ich die Variablen auf mehrere .bss-Sektionen
aufteile?
Viele Grüße
crozeg
.
.bss2 :
{
_sbss2 = .; /* define a global symbol at bss start */
bss2_start = _sbss2;
*(.bss2)
*(.bss2*)
*(COMMON)
. = ALIGN(4);
_ebss2 = .; /* define a global symbol at bss end */
bss2_end = _ebss2;
} >ERAM1
und bei den Variablen Deklaration "__attribute__((section(".bss2")))"
das sollte dann passen. Vllt gibts auch n Makefile generator von
Em:Blocks? Das man sowas über die Ide einstellen kann. Crossworks kann
so was.
Ch. Ziegler schrieb:> Jetzt ist meine .bss-Sektion so groß das sie in keine der RAMs passt.> Ich will dem LinkerSkript gerne folgendes sagen:> "Schreibe die .bss-Sektion erstmal in IRAM1 bis es voll ist, dann> schreibe weiter in IRAM2 bis es voll ist und dann weiter in ERAM1."
Ich hab's jetzt nicht selbst ausprobiert, das müsste aber eigentlich so
gehen:
1
.bss1 :
2
{
3
_sbss1 = .; /* define a global symbol at bss start */
4
_bss_start_ = _sbss1;
5
dir1/*(.bss)
6
dir1/*(.bss*)
7
dir1/*(COMMON)
8
9
. = ALIGN(4);
10
_ebss = .; /* define a global symbol at bss end */
11
_bss_end_ = _ebss1;
12
} >IRAM1
13
14
.bss2 :
15
{
16
_sbss2 = .; /* define a global symbol at bss start */
17
_bss2_start_ = _sbss2;
18
dir2/*(.bss)
19
dir2/*(.bss*)
20
dir2/*(COMMON)
21
22
. = ALIGN(4);
23
_ebss2 = .; /* define a global symbol at bss end */
24
_bss2_end_ = _ebss2;
25
} > IRAM2
D.h. Du "sammelst" die Objektdateien in zwei Verzeichnissen, aus denen
sich der Linker dann pro Segment bedient. So was wie einen
"automatischen Überlauf" gibt's meiner Ansicht nach nicht.
Ja, das nervt, dass die uC-Hersteller das RAM so zerstueckeln :(
Generell finde ich es aber sowieso schoener, die sections explizit im
C-code anzugeben, damit man mit dem Linker-Script noch jonglieren kann.
Wo man den Stack hinlegt wird ja wohl auch zu einer ganz wichtigen
Entscheidung - vielleicht wichtiger als die die .bss Variablen.
Ich vermeide die .bss-Variablen meist zugunsten von Stack-Variablen,
wegen deren Speicher-Wiederverwertung ;-)
Aber ich hoffe, dass noch ein Toolchain-Guru hier eine L"osung bietet.
Ich koennte sowas n"amlich sinngemaess in der .text brauchen...
Wie und wo sage ich dem LinkerScript welche Dateien/Objekte er in welche
Section legen soll?
Kennt jemand vielleicht ein gutes Tutorial für die ganze Sache hier?
Viele Grüße,
crozeg
.
Tec Nologic schrieb:> und bei den Variablen Deklaration "__attribute__((section(".bss2")))"
Gibt es anstatt "__attribute__((section(".bss2")))" auch ein #pragma für
eine ganze C-Datei?
Markus F. schrieb:> D.h. Du "sammelst" die Objektdateien in zwei Verzeichnissen, aus denen> sich der Linker dann pro Segment bedient. So was wie einen> "automatischen Überlauf" gibt's meiner Ansicht nach nicht.
Wie teilt man die *.o-Dateien auf verschiedene Unterverzeichnisse auf?
Die Sourcedateien liegen bereits in verschiedenen Unterordnern, die
O-Dateien werden beim Bauen in einem einzigen Ordner abgelegt.
Viele Grüße
crozeg
There are two ways to include more than one section:
2
3
*(.text .rdata)
4
*(.text) *(.rdata)
5
6
The difference between these is the order in which the `.text' and `.rdata' input sections will appear in the output section. In the first example, they will be intermingled. In the second example, all `.text' input sections will appear first, followed by all `.rdata' input sections.
7
8
You can specify a file name to include sections from a particular file. You would do this if one or more of your files contain special data that needs to be at a particular location in memory. For example:
9
10
data.o(.data)
1
.bss2 :
2
{
3
_sbss2 = .; /* define a global symbol at bss start */
4
_bss2_start_ = _sbss2;
5
main.o(.bss) // hier wird bss von main gesetzt.
6
foo.o(.bss) // usw.
7
dir2/*(.bss) //
8
dir2/*(.bss*)
9
dir2/*(COMMON)
10
11
. = ALIGN(4);
12
_ebss2 = .; /* define a global symbol at bss end */
@tecnologic: das wird so nicht funktionieren.
Das würde bedeuten, daß der Linker selbstständig das nächste Segment
nutzen würde, wenn er feststellt, daß eins "voll" ist (was er leider
nicht tut). Es bleibt nichts anderes übrig, als den Überlauf "händisch"
zu steuern.
@mfro
Jop, er muss jetzt aufpassen das die sections der files in die bss bzw.
die bss2 section passen. Das ein riesen Array der Speicher aus dem
internen wie externen Ram nehmen soll nicht geht, wurde ja bereits
erklärt.
Schonmal vielen dank, ihr habt mir schon viel geholfen.
Momentan siehen meine bss-Sektionen wie folgt aus:
(Hoffe das stimmt soweit)
1
...
2
3
.bss2:
4
{
5
_sbss2=.;/* define a global symbol at bss start */
6
_bss2_start_=_sbss2;
7
8
obj/main.o(.bss.bss*COMMON)
9
obj/hwe.o(.bss.bss*COMMON)
10
11
/* FreeRTOS Objects */
12
obj/port.o(.bss.bss*COMMON)
13
obj/heap_4.o(.bss.bss*COMMON)
14
obj/croutine.o(.bss.bss*COMMON)
15
obj/event_groups.o(.bss.bss*COMMON)
16
obj/list.o(.bss.bss*COMMON)
17
obj/queue.o(.bss.bss*COMMON)
18
obj/tasks.o(.bss.bss*COMMON)
19
obj/timers.o(.bss.bss*COMMON)
20
21
.=ALIGN(4);
22
_ebss2=.;/* define a global symbol at bss end */
23
_bss2_end_=_ebss2;
24
}>IRAM1
25
26
.bss:
27
{
28
_sbss=.;/* define a global symbol at bss start */
29
_bss_start_=_sbss;
30
31
*(.bss)
32
*(.bss*)
33
*(COMMON)
34
35
.=ALIGN(4);
36
_ebss=.;/* define a global symbol at bss end */
37
_bss_end_=_ebss;
38
}>ERAM1
39
40
...
Aber leider läuft meine Firmware nicht richtig.
Was genau scheinbar scheinen einige Dateien andere nicht mehr zu
finden/erreichen?
Und was genau macht so ein AT befehl in LinkerScripts?
Zb im folgenden am ende meiner data-Sektion:
1
...
2
.data:
3
{
4
.=ALIGN(4);
5
_sdata=.;/* create a global symbol at data start */
Ch. Ziegler schrieb:> Und was genau macht so ein AT befehl in LinkerScripts?> Zb im folgenden am ende meiner data-Sektion:>
1
>...
2
>.data:
3
>{
4
>.=ALIGN(4);
5
>_sdata=.;/* create a global symbol at data start */
6
>*(.data)/* .data sections */
7
>*(.data*)/* .data* sections */
8
>
9
>.=ALIGN(4);
10
>_edata=.;/* define a global symbol at data end */
11
>}>ERAM1AT>IROM1
12
>...
>> Viele Grüße> crozeg
das AT-Konstrukt packt die Objektdaten an die erste Adresse (ERAM1),
reloziert den Code aber so, daß sie ab der zweiten Adresse (IROM1)
referenziert werden.
Für dich bedeutet das, daß dein ausführbarer Code seine Daten ab der
Startadresse IROM1 erwartet (wo sie aber nicht sind, falls Du sie nicht
beim Programmstart umkopierst).
Das kann so m.E. nicht gut gehen.
Hallo,
danke schonmal, seit dem nullen im startup code läufts schon besser.
Zumindest die main.o.
1
...
2
.=ALIGN(4);
3
.bss_iram1:
4
{
5
_sbss_iram1=.;/* define a global symbol at bss start */
6
_bss_iram1_start_=_sbss_iram1;
7
8
obj/main.o(.bss.bss*COMMON)
9
obj/rm_tcp.o(.bss.bss*COMMON)
10
11
/* FreeRTOS Objects */
12
obj/port.o(.bss.bss*COMMON)
13
obj/heap_4.o(.bss.bss*COMMON)
14
obj/croutine.o(.bss.bss*COMMON)
15
obj/event_groups.o(.bss.bss*COMMON)
16
obj/list.o(.bss.bss*COMMON)
17
obj/queue.o(.bss.bss*COMMON)
18
obj/tasks.o(.bss.bss*COMMON)
19
obj/timers.o(.bss.bss*COMMON)
20
21
.=ALIGN(4);
22
_ebss_iram1=.;/* define a global symbol at bss end */
23
_bss_iram1_end_=_ebss_iram1;
24
}>IRAM1
25
26
27
.=ALIGN(4);
28
.bss_eram1:
29
{
30
/* This is used by the startup in order to initialize the .bss secion */
31
_sbss_eram1=.;/* define a global symbol at bss start */
32
__bss_eram1_start__=_sbss_eram1;
33
34
*(.bss)
35
*(.bss*)
36
*(COMMON)
37
38
.=ALIGN(4);
39
_ebss_eram1=.;/* define a global symbol at bss end */
40
__bss_eram1_end__=_ebss_eram1;
41
}>ERAM1
42
...
Wenn ich die Zeile "obj/rm_tcp.o(.bss .bss* COMMON)" zur bss_iram1
hinzufüge funktioniert nichts mehr. Der Compiler wirft folgendes:
1
Linking executable: bin\Debug\FreeRTOS4EGM.elf
2
c:/program files (x86)/emblocks/1.45/share/em_armgcc/bin/../lib/gcc/arm-none-eabi/4.7.3/../../../../arm-none-eabi/lib/armv7e-m/fpu\libc_n.a(lib_a-findfp.o): In function `_cleanup_r':
3
findfp.c:(.text._cleanup_r+0x0): multiple definition of `_cleanup_r'
4
c:/program files (x86)/emblocks/1.45/share/em_armgcc/bin/../lib/gcc/arm-none-eabi/4.7.3/../../../../arm-none-eabi/lib/armv7e-m/fpu\libc.a(lib_a-findfp.o):findfp.c:(.text._cleanup_r+0x0): first defined here
5
c:/program files (x86)/emblocks/1.45/share/em_armgcc/bin/../lib/gcc/arm-none-eabi/4.7.3/../../../../arm-none-eabi/lib/armv7e-m/fpu\libc_n.a(lib_a-findfp.o): In function `__sfmoreglue':
6
findfp.c:(.text.__sfmoreglue+0x0): multiple definition of `__sfmoreglue'
7
c:/program files (x86)/emblocks/1.45/share/em_armgcc/bin/../lib/gcc/arm-none-eabi/4.7.3/../../../../arm-none-eabi/lib/armv7e-m/fpu\libc.a(lib_a-findfp.o):findfp.c:(.text.__sfmoreglue+0x0): first defined here
8
c:/program files (x86)/emblocks/1.45/share/em_armgcc/bin/../lib/gcc/arm-none-eabi/4.7.3/../../../../arm-none-eabi/lib/armv7e-m/fpu\libc_n.a(lib_a-findfp.o): In function `_cleanup':
9
findfp.c:(.text._cleanup+0x0): multiple definition of `_cleanup'
10
c:/program files (x86)/emblocks/1.45/share/em_armgcc/bin/../lib/gcc/arm-none-eabi/4.7.3/../../../../arm-none-eabi/lib/armv7e-m/fpu\libc.a(lib_a-findfp.o):findfp.c:(.text._cleanup+0x0): first defined here
11
c:/program files (x86)/emblocks/1.45/share/em_armgcc/bin/../lib/gcc/arm-none-eabi/4.7.3/../../../../arm-none-eabi/lib/armv7e-m/fpu\libc_n.a(lib_a-findfp.o): In function `__sinit':
12
findfp.c:(.text.__sinit+0x0): multiple definition of `__sinit'
13
c:/program files (x86)/emblocks/1.45/share/em_armgcc/bin/../lib/gcc/arm-none-eabi/4.7.3/../../../../arm-none-eabi/lib/armv7e-m/fpu\libc.a(lib_a-findfp.o):findfp.c:(.text.__sinit+0x0): first defined here
14
c:/program files (x86)/emblocks/1.45/share/em_armgcc/bin/../lib/gcc/arm-none-eabi/4.7.3/../../../../arm-none-eabi/lib/armv7e-m/fpu\libc_n.a(lib_a-findfp.o): In function `__sfp':
15
findfp.c:(.text.__sfp+0x0): multiple definition of `__sfp'
16
c:/program files (x86)/emblocks/1.45/share/em_armgcc/bin/../lib/gcc/arm-none-eabi/4.7.3/../../../../arm-none-eabi/lib/armv7e-m/fpu\libc.a(lib_a-findfp.o):findfp.c:(.text.__sfp+0x0): first defined here
17
c:/program files (x86)/emblocks/1.45/share/em_armgcc/bin/../lib/gcc/arm-none-eabi/4.7.3/../../../../arm-none-eabi/lib/armv7e-m/fpu\libc_n.a(lib_a-findfp.o): In function `__sfp_lock_acquire':
18
findfp.c:(.text.__sfp_lock_acquire+0x0): multiple definition of `__sfp_lock_acquire'
19
c:/program files (x86)/emblocks/1.45/share/em_armgcc/bin/../lib/gcc/arm-none-eabi/4.7.3/../../../../arm-none-eabi/lib/armv7e-m/fpu\libc.a(lib_a-findfp.o):findfp.c:(.text.__sfp_lock_acquire+0x0): first defined here
20
c:/program files (x86)/emblocks/1.45/share/em_armgcc/bin/../lib/gcc/arm-none-eabi/4.7.3/../../../../arm-none-eabi/lib/armv7e-m/fpu\libc_n.a(lib_a-findfp.o): In function `__sfp_lock_release':
21
findfp.c:(.text.__sfp_lock_release+0x0): multiple definition of `__sfp_lock_release'
22
c:/program files (x86)/emblocks/1.45/share/em_armgcc/bin/../lib/gcc/arm-none-eabi/4.7.3/../../../../arm-none-eabi/lib/armv7e-m/fpu\libc.a(lib_a-findfp.o):findfp.c:(.text.__sfp_lock_release+0x0): first defined here
23
c:/program files (x86)/emblocks/1.45/share/em_armgcc/bin/../lib/gcc/arm-none-eabi/4.7.3/../../../../arm-none-eabi/lib/armv7e-m/fpu\libc_n.a(lib_a-findfp.o): In function `__sinit_lock_acquire':
24
findfp.c:(.text.__sinit_lock_acquire+0x0): multiple definition of `__sinit_lock_acquire'
25
c:/program files (x86)/emblocks/1.45/share/em_armgcc/bin/../lib/gcc/arm-none-eabi/4.7.3/../../../../arm-none-eabi/lib/armv7e-m/fpu\libc.a(lib_a-findfp.o):findfp.c:(.text.__sinit_lock_acquire+0x0): first defined here
26
c:/program files (x86)/emblocks/1.45/share/em_armgcc/bin/../lib/gcc/arm-none-eabi/4.7.3/../../../../arm-none-eabi/lib/armv7e-m/fpu\libc_n.a(lib_a-findfp.o): In function `__sinit_lock_release':
27
findfp.c:(.text.__sinit_lock_release+0x0): multiple definition of `__sinit_lock_release'
28
c:/program files (x86)/emblocks/1.45/share/em_armgcc/bin/../lib/gcc/arm-none-eabi/4.7.3/../../../../arm-none-eabi/lib/armv7e-m/fpu\libc.a(lib_a-findfp.o):findfp.c:(.text.__sinit_lock_release+0x0): first defined here
29
c:/program files (x86)/emblocks/1.45/share/em_armgcc/bin/../lib/gcc/arm-none-eabi/4.7.3/../../../../arm-none-eabi/lib/armv7e-m/fpu\libc_n.a(lib_a-findfp.o): In function `__fp_lock_all':
30
findfp.c:(.text.__fp_lock_all+0x0): multiple definition of `__fp_lock_all'
31
c:/program files (x86)/emblocks/1.45/share/em_armgcc/bin/../lib/gcc/arm-none-eabi/4.7.3/../../../../arm-none-eabi/lib/armv7e-m/fpu\libc.a(lib_a-findfp.o):findfp.c:(.text.__fp_lock_all+0x0): first defined here
32
c:/program files (x86)/emblocks/1.45/share/em_armgcc/bin/../lib/gcc/arm-none-eabi/4.7.3/../../../../arm-none-eabi/lib/armv7e-m/fpu\libc_n.a(lib_a-findfp.o): In function `__fp_unlock_all':
33
findfp.c:(.text.__fp_unlock_all+0x0): multiple definition of `__fp_unlock_all'
34
c:/program files (x86)/emblocks/1.45/share/em_armgcc/bin/../lib/gcc/arm-none-eabi/4.7.3/../../../../arm-none-eabi/lib/armv7e-m/fpu\libc.a(lib_a-findfp.o):findfp.c:(.text.__fp_unlock_all+0x0): first defined here
35
collect2.exe: error: ld returned 1 exit status
36
Process terminated with status 1 (0 minutes, 5 seconds)
37
0 errors, 165 warnings (0 minutes, 5 seconds)
Siehe auch angehängtes Bild.
Im Bild sieht man auch das der Build mit 0 Errors abgeschlossen wurde,
aber ich kann den Code nicht Debuggen/ins Target laden.
Viele Grüße
crozeg
Das sieht mir jetzt so aus, als ob das mit dem Linkerscript nichts zu
tun hätte - Du scheinst zu versuchen, die Newlib doppelt zuzulinken.
Laß' mal deinen Linker-Aufruf sehen.
Hallo,
ich mache keinen expliziten Linker-Aufruf, da ich ja mit der IDE
Em::Blocks arbeite/baue.
In den Einstellungen habe ich folgende "extra command-line arguments"
gefunden, vielleicht meinst du ja die:
Hallo,
seit ich in den Em::Blocks Setting, bei Linker Settings, die "default
libraries" angehakt (siehe angehägtes Bild). Jetz bauts und läuft (fürs
erste).
War das richtig?
Viele Grüße
crozeg