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.
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).
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.