Forum: Compiler & IDEs gcc / .ld: AT91SAM7S256 Speicheraufteilung


von Peter P. (uncle-sam7)


Angehängte Dateien:

Lesenswert?

Hallo NG,

ich bin gerade dabei einen SID-Player auf Basis eines AT91SAM7S256 zu 
machen. Habe mich für diesen MC entschieden, weil der 64 KB SRAM hat, 
was ja schon mal eine tolle Parallele zum C64 ist :-)

Leider weiß ich noch nicht viel übers Linken. Der Player funktioniert 
momentan soweit, dass er ein "festes" SID-Stück abspielt, das sich an

- - 8< - - 8< - - Auszug aus .ld snip - - 8< - - 8< - -
.sid 0x20c000 : {
 *(.sid)
}
- - 8< - - 8< - - Auszug aus .ld snap- - 8< - - 8< - -

befindet (im C64 original an $C000).

Im C-Programm sage ich dann:
static unsigned char mysid[] __attribute__((section(".sid"))) = {
  162, 25, 169, 0, 157, 0, 212, 189 ...
}
um die Daten an die entsprechende Stelle zu laden.
Das funktioniert bereits.

So, jetzt zu meiner Frage: Ich möchte ja die SID-Files von SD-Karte in 
den Speicher laden (kann theoretisch überall zwischen 0x200000 - 
0x20FFFF sein). Deshalb würde ich gerne alle Dinge, die das Programm am 
Ende benötigt, um vom EEPROM zu laufen an von mir definierten Stellen im 
Speicher haben (typischer Weise eher am Anfang des Speichers).

Also wie lege ich die Positionen & ggf. deren Größe für
- Stack
- Variablen
- und sonstigen Kram, der SRAM benötigt
fest?

Vielen Dank für jede Hilfe.
Peter

PS.: verwende bei mir hier yagarto ohne Eclipse.

von Andreas B. (Gast)


Lesenswert?

Peter Pippinger schrieb:
> Also wie lege ich die Positionen & ggf. deren Größe für
> - Stack

Stack wird in C benutzt, aber nicht manipuliert. Das heißt, dein 
Startup-Code muss das SP Register initialisieren, also machst du da was 
du willst.

Größe festlegen geht dabei ohnehin nicht, der Stack wächst so wie er 
verwendet wird. Einfluss also nur über Rekursionstiefe und Größe der 
lokalen Variablen.

Wenn du wie in dem Atmel-Beispielen ohne Multitasking arbeitest und 
alles in einem Hauptthread und Interrupts erledigst, braucht du auch nur 
zwei Stacks, Supervisor und Interrupt, und der Interrupt Stack ist 
begrenzt weil man bei den Interrupt-Dispatcher auf den Supervisor-Stack 
umschalten lässt: Beitrag "Re: Interrupt PWM beim Sam7s256"

> - Variablen

Ausführungsadresse (VMA) der Sektionen .data und .bss. Wenn du mit 
Speicherregionen im Linkerscript arbeitest, werden die vom Anfang 
beginnend befüllt.

> - und sonstigen Kram, der SRAM benötigt
> fest?

Sonstiger Kram? Interrupt-Vektoren, wenn du die im RAM liegen hast, aber 
deren Adresse ist ohnehin festgelegt (ab 0, also Anfang vom RAM und RAM 
an Adresse 0 gemappt).

von Peter (Gast)


Lesenswert?

Andreas B. schrieb:

Vielen Dank, Andreas für Deine Ausführungen.

>> Also wie lege ich die Positionen & ggf. deren Größe für
>> - Stack
>
> Stack wird in C benutzt, aber nicht manipuliert. Das heißt, dein
> Startup-Code muss das SP Register initialisieren, also machst du da was
> du willst.

OK, verstehe ich.

> Größe festlegen geht dabei ohnehin nicht, der Stack wächst so wie er
> verwendet wird. Einfluss also nur über Rekursionstiefe und Größe der
> lokalen Variablen.

Der wächst ja nach unten, wenn ich mich recht erinnere?
also z.B. 0x020ffff, 0x020fffe...

> Wenn du wie in dem Atmel-Beispielen ohne Multitasking arbeitest und
> alles in einem Hauptthread und Interrupts erledigst, braucht du auch nur
> zwei Stacks, Supervisor und Interrupt, und der Interrupt Stack ist
> begrenzt weil man bei den Interrupt-Dispatcher auf den Supervisor-Stack
> umschalten lässt: Beitrag "Re: Interrupt PWM beim Sam7s256"

Ja, soll alles ohne Interrupts ablaufen.

>> - Variablen
> Ausführungsadresse (VMA) der Sektionen .data und .bss. Wenn du mit
> Speicherregionen im Linkerscript arbeitest, werden die vom Anfang
> beginnend befüllt.

Hier wäre ein kleines Beispiel super. Wenn ich z.B.
int x = 0; definiere, dass das dann irgendwo zwischen 0x0200400 und 
0x0200800 liegt.

>> - und sonstigen Kram, der SRAM benötigt
>> fest?
>
> Sonstiger Kram? Interrupt-Vektoren, wenn du die im RAM liegen hast, aber
> deren Adresse ist ohnehin festgelegt (ab 0, also Anfang vom RAM und RAM
> an Adresse 0 gemappt).

Sorry für die saloppe Ausdrucksweise. Ich meine damit alles "Flüchtige", 
was mein C-Code nicht aus dem EEPROM raus verwenden kann, wie Variablen 
usw...

Also unterm Strich möchte ich einfach einen bestimmten Bereich im SRAM 
FESTLEGEN, mit dem der C-Compiler dann machen darf, was er mag. Wenn der 
Stackpointer da rausläuft, dann ists auch nicht sooo schlimm... Aber all 
die Anderen Dinge würde ich gerne an FESTEN Adressen wissen.

Viele Grüße,
Peter

von Andreas B. (Gast)


Lesenswert?

Peter schrieb:
> Der wächst ja nach unten, wenn ich mich recht erinnere?
> also z.B. 0x020ffff, 0x020fffe...

Ja, eigentlich überall. Ich könnte aus dem Kopf jetzt kein System 
nennen, wo der Stack nicht nach unten wächst. In der ARM Architektur 
wären zwar alle Möglichkeiten vertreten, aber in Thumb schon nicht mehr. 
Praktisch wird auch nur der absteigende Stack verwendet.

Mit vordefinierten stack_space (Basis des Stacks), stack_size 
(Gesamtgröße Stack) und irq_stack_size (Größe davon für IRQ reserviert):
1
        .equ    stack_size, 1024
2
        .equ    irq_stack_size, 96
3
        .lcomm  stack_space , stack_size
4
5
reset_start:
6
        ldr     r4, =stack_space+stack_size
7
8
        @ init stacks for SVC and IRQ mode, others are unused
9
        msr     CPSR_c, MODE_IRQ|I_BIT|F_BIT
10
        mov     sp, r4                  @ topmost stack for IRQ
11
        msr     CPSR_c, MODE_SVC|I_BIT|F_BIT
12
        sub     sp, r4, irq_stack_size  @ use stack directly below IRQ stack
Das alles mit dem erwähnten IRQ Dispatcher, der dafür sorgt, dass vom 
IRQ Stack nur eine genau begrenzte Menge genutzt wird. Wenn du nun gar 
keine Interrupts nutzt kannst du natürlich die Initialisierung vom IRQ 
Stack lassen. Wenn du andererseits noch mehr Betriebsmodi als nur 
Supervisor und IRQ verwendest musst du zusätzlich auch deren 
Stackpointer initialisieren.

Peter schrieb:
> Hier wäre ein kleines Beispiel super. Wenn ich z.B.
> int x = 0; definiere, dass das dann irgendwo zwischen 0x0200400 und
> 0x0200800 liegt.

Dann gib deiner .data Sektion eine feste Adresse genau wie beim .sid. 
Wenn du statt dessen Regionen verwendest wie etwa >RAM dann nimmt der 
Linker selbst die erste freie Adresse aus der Region. Wenn sich dann was 
mit anderen Sektionen überlappt (wie mit dem .sid) oder nicht passt dann 
wird der Linker schon meckern.

Wenn es wirklich sein muss, kann ja eine Region dafür definiert, die 
entsprechend begrenzt ist.

Man kann auch für jede Sektion eine feste Adresse vorgeben, etwa:
1
.data 0x200200 : {
2
        eins.o(.data)
3
        . = 0x100;
4
        zwei.o(.data)
5
        . = 0x300;
6
        drei.o(.data)
usw., aber das wird ja wohl kaum nötig sein und verschwendet nur den 
Platz, der übersprungen wird.

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.