Forum: Mikrocontroller und Digitale Elektronik Probleme mit dem Remap Befehl beim AT91SAM7X mit RTOS


von STEFAN (Gast)


Angehängte Dateien:

Lesenswert?

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

von gerhard (Gast)


Lesenswert?

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

von Martin T. (mthomas) (Moderator) Benutzerseite


Lesenswert?

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.

von STEFAN (Gast)


Angehängte Dateien:

Lesenswert?

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
Noch kein Account? Hier anmelden.