Hallo Zusammen,
ich habe ein Probklem bei der initialisierung des AT91SAM7X. Ich benute
ihn zusammen mit dem RTOS freeRTOS, wobei ich mir dazu ein Beispiel von
der freeRTOS Seite runtergeladen habe. Als Tipp steht hier ein
bestehendes beispiel so zu ändern, dass man es auf die eigenen
Bedürfnisse anpasst.
Gesagt, getan.
Funktioniert sowiet, bis auf den Remap befehl. Um die maximale
Performance zu erreichen will ich den Code aus dem RAm laufen lassen und
musss dazu den Speicherbreich remappen. Hierzu copiere ich den gesamten
Code aus dem Flash in den RAM und setzte dann das Remap Bit.
memcpy(0x00200000,0x00100000,0x2000);
AT91C_BASE_MC->MC_RCR = AT91C_MC_RCB;
Das ganze mache ich in der LowLevelInit.c, welche nach den Befehlen mit
dem Wort SECTION ausgeführt wird (siehe unten).
Von den Speicherbereichen passt das soweit auch noch, nur dass ich mir
damit selber die Beine wegziehe und mir damit meine verschiedenen Stacks
überschreibe. In der CStartup.s Datei, in welcher die Stacks
initialisiert werden steht ein Befehl den ich nicht verstehe.
Evtl. kann mir jeamnd diesen Erklären:
Ich kopier hier mal einen größeren Zusammenhang...
;-----------------------------------------------------------------------
-------
; ?INIT
; Program entry.
;-----------------------------------------------------------------------
-------
SECTION FIQ_STACK:DATA:NOROOT(3) ??????
SECTION IRQ_STACK:DATA:NOROOT(3) ??????
SECTION SVC_STACK:DATA:NOROOT(3) ??????
SECTION ABT_STACK:DATA:NOROOT(3) ??????
SECTION UND_STACK:DATA:NOROOT(3) ??????
SECTION CSTACK:DATA:NOROOT(3) ??????
SECTION text:CODE:NOROOT(2) ??????
REQUIRE __vector ??????
EXTERN ?main ??????
PUBLIC __iar_program_start ??????
EXTERN AT91F_LowLevelInit ??????
__iar_program_start:
;-----------------------------------------------------------------------
-------
;- Low level Init is performed in a C function: AT91F_LowLevelInit
;- Init Stack Pointer to a valid memory area before calling
AT91F_LowLevelInit
;-----------------------------------------------------------------------
-------
;- Retrieve end of RAM address
ldr r13,=TOP_OF_MEMORY ;- Temporary stack
in internal RAM for Low Level Init execution
ldr r0,=AT91F_LowLevelInit
mov lr, pc
bx r0 ;- Branch on C
function (with interworking)
; Initialize the stack pointers.
; The pattern below can be used for any of the exception stacks:
; FIQ, IRQ, SVC, ABT, UND, SYS.
; The USR mode uses the same stack as SYS.
; The stack segments must be defined in the linker command file,
; and be declared above.
mrs r0,cpsr ; Original
PSR value
bic r0,r0,#MODE_BITS ; Clear the
mode bits
orr r0,r0,#SVC_MODE ; Set SVC
mode bits
msr cpsr_c,r0 ; Change the
mode
ldr sp,=SFE(SVC_STACK) ; End of
SVC_STACK
bic r0,r0,#MODE_BITS ; Clear the mode
bits
orr r0,r0,#UND_MODE ; Set UND
mode bits
msr cpsr_c,r0 ; Change the
mode
ldr sp,=SFE(UND_STACK) ; End of
UND_STACK
bic r0,r0,#MODE_BITS ; Clear the
mode bits
orr r0,r0,#ABT_MODE ; Set ABT
mode bits
msr cpsr_c,r0 ; Change the
mode
ldr sp,=SFE(ABT_STACK) ; End of
ABT_STACK
bic r0,r0,#MODE_BITS ; Clear the
mode bits
orr r0,r0,#FIQ_MODE ; Set FIQ
mode bits
msr cpsr_c,r0 ; Change the
mode
ldr sp,=SFE(FIQ_STACK) ; End of
FIQ_STACK
;- Init the FIQ register
ldr r8, =AT91C_BASE_AIC
bic r0,r0,#MODE_BITS ; Clear the
mode bits
orr r0,r0,#IRQ_MODE ; Set IRQ
mode bits
msr cpsr_c,r0 ; Change the
mode
ldr sp,=SFE(IRQ_STACK) ; End of
IRQ_STACK
bic r0,r0,#MODE_BITS ; Clear the
mode bits
orr r0,r0,#SYS_MODE ; Set System
mode bits
msr cpsr_c,r0 ; Change the
mode
ldr sp,=SFE(CSTACK) ; End of
CSTACK
;-----------------------------------------------------------------------
-
Hab die komplette Startup Datei nochmal als Anhang dran gehangen.
Meine Fragen jetzt:
Wo werden den die Stacks hingelegt (Speicherbereich)? Und wie kann, bzw.
muss ich sie legen, damit ich sie mit dem Remap Befehl nicht
überschreibe und es trotzdem funktioniert?
Hoffe jemand kann mir da helfen.
Viele Dank schonmal im Vorraus
MfG
Stefan
hallo stefan, ich würd dir empfehlen, nur die zeitkritischen funktionen ins ram zu kopieren. wenn du bei der definition der funktion dem compiler/linker mitteilst dass welche funktionen im ram liegen sollen dann macht das ganze der startup-code für dich. unter iar workbench gibt es dafür das schlüsselwort "__ramfunc", unter gcc kenne ich es leider nicht, es gibt aber dort auch diese möglichkeit. gruss gerhard
Vorab: nutze EWARM fast nie und dann auch nur zum Spielen, folgendes also nur ein paar Ansätze. IAR bietet Support für ihre Produkte, dort schon gefragt? >... > Funktioniert sowiet, bis auf den Remap befehl. Um die maximale > Performance zu erreichen will ich den Code aus dem RAm laufen lassen und > musss dazu den Speicherbreich remappen. Hierzu copiere ich den gesamten > Code aus dem Flash in den RAM und setzte dann das Remap Bit. > > memcpy(0x00200000,0x00100000,0x2000); > AT91C_BASE_MC->MC_RCR = AT91C_MC_RCB; Dem Linker wurde nicht mitgeteilt, dass ein Teil der RAM-Bereichs für Code genutzt werden soll. Wenn man alle sections in die RAM region linkt, sollte der Linker Adressebereiche für code, rodata, data, stacks automatisch zuweisen. Kann man wohl per Linker configuration file (Linker-Script auf IARisch) machen. Nur der Startup-Code und die Kopierroutine für alle sections bleiben im ROM. > Das ganze mache ich in der LowLevelInit.c, welche nach den Befehlen mit > dem Wort SECTION ausgeführt wird (siehe unten). > > Von den Speicherbereichen passt das soweit auch noch, nur dass ich mir > damit selber die Beine wegziehe und mir damit meine verschiedenen Stacks > überschreibe. Warum "passt" das mit den Speicherbereichen. Gibt es eine Art Map-File, dass die vom Linker zugewiesenen Adressen für die sections auflistet? > In der CStartup.s Datei, in welcher die Stacks > initialisiert werden steht ein Befehl den ich nicht verstehe. SFE? Wenn ja: gibt w.r.e die letzte Adresse einer section zurück, würde auch zum restlichen Code passen. > Meine Fragen jetzt: > > Wo werden den die Stacks hingelegt (Speicherbereich)? In jeweils eigene sections in data. In welcher Memory region data liegt, wird im linker configuration-file festgelegt. Mglw. auch die Position der Stacks, kann man aber erst was zu sagen, wenn man ins Linker-Conf.-File schaut. > Und wie kann, bzw. > muss ich sie legen, damit ich sie mit dem Remap Befehl nicht > überschreibe und es trotzdem funktioniert? Am einfachsten an das Ende des RAM-Speichers ohne eigene Sections sondern mit vorgegebenen Größen. Sollte in den Beispielcodes von Atmel (Software-Package) demonstriert sein. Ist zumindest so für die GNU Beispiele. Ist aber nur die halbe Miete, neben den Stacks werden ja noch schreib/lese Variablen im RAM vorwaltet. Falls man an den Programmcode auch Speicheraddressen kopiert, die eigentlich vom Linker für Variablen zugewiesen wurden, passiert schlimmes. Ein Holzhammer-Lösung wäre evtl, wenn man die Origin der Region RAM so einstellt, dass genug Platz für den Code im RAM freibleibt. Ist aber nicht wirklich schick. Sollte durch Einstellungen im Linker-Conf.-File besser zu lösen sein. (Hoppla, bei der Vorschau gesehen, das dies von gerhard schon angemerkt wurde, ich lasse es einfach mal stehen:) Ansonsten bleibt noch die Möglichkeit per RAMFUNC (o.ä.) nur bestimmte Funktionen in RAM zu legen (IRQ-Wrapper, Handler usw.), Assembler code dann aber auch genau anschauen, insbes. wenn man von dort andere Funktionen z.B. aus der libc aufruft, denn die können sich noch im ROM befinden.
Hallo zusammen,
danke schonmal für die Antworten!
Hab auch gleich mal ins Linkerfile geschaut. Sieht für mich als Laien
recht gut aus...
place in ROM_region { readonly };
place in RAM_region { readwrite,
block CSTACK, block SVC_STACK, block IRQ_STACK,
block FIQ_STACK, block UND_STACK, block ABT_STACK, block HEAP };
Davor werden noch die Größen der Stacks definiert. Hab jetzt auch mal
das Linkerfile mit rangehängt
Das bedeutet doch fürs remappen, er nimmt den Code im ROM und packt ihn
an den Anfang vom RAM. Danach werden die ganzen Stacks ins RAM gelegt.
Mittlerweile glaub ich mein Remap Befehl kommt einfach zum falschen
Zeitpunkt. Hab auch gelesen dass vor dem Remappen die Execption Vektoren
ins RAM kopiert werden sollen, damit wenn beim Remappen was schief geht,
auch das noch abgefangen werden kann. Wann soll ich das am besten
machen? In meiner Cstartup.s Datei?
Dass das Remap durchgeführt wird sehe ich beim debuggen. Da sehe ich ja
die Befehle die an der Adresse 0x00 sind und vergleiche die einfach mit
den Befehlen am Anfang vom RAM. Das passt dann.
Auch wenn ich nur bestimmte Funktionen in den RAM lege, würde ich das
Thema gern verstehen. Da ich ja auch ein Betriebssystem verwende, müsste
ich dann wohl recht viele Funktionen in den RAM mappen, wieso also nicht
gleich alles? Die gesamte Applikation wird auf keinen Fall größer als
64k.
Ach so, was meinst du denn mit SFE? und was mit w.r.e?
"SFE? Wenn ja: gibt w.r.e die letzte Adresse einer section zurück, würde
auch zum restlichen Code passen"
Glaub wir sind der Lösung schon recht nahe. Nur der entscheidende Hint
fehlt noch...
Grüße Stefan
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.