mikrocontroller.net

Forum: Compiler & IDEs ARM7 - Funktionen ins Ram kopieren


Autor: Tilo L. (katagia)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

ich will einige Funktionen (arm-gcc) ins Ram kopieren, um deren 
Ausführzeiten zu beschleidnigen. Das Flash ist nur mit 16bit verbunden.

Unter http://www.embeddedrelated.com/groups/lpc2000/show/5031.php habe 
ich eine Diskussion über das Thema gefunden. Dort taucht folgender 
Abschnitt auf:

So to summarize, to get and use a function in RAM you only need to do
three things:

(1) Have an init in the startup code for the .data section.
(2) Use the __attribute__((section(".data"))) on the functions.
(3) Define function pointer variables for the functions and make
indirect calls using those.


Zu Punkt 1:
In meinem Startup-Code gibt es folgenden Abschnitt:
        /* copy initialized variables .data section  (Copy from ROM to RAM) */
                ldr     R1, =_etext
                ldr     R2, =_data
                ldr     R3, =_edata
1:            cmp     R2, R3
                ldrlo   R0, [R1], #4
                strlo   R0, [R2], #4
                blo     1b

        /* Clear uninitialized variables .bss section (Zero init)  */
                mov     R0, #0
                ldr     R1, =_bss_start
                ldr     R2, =_bss_end
2:        cmp     R1, R2
                strlo   R0, [R1], #4
                blo     2b

        /* Enter the C code  */
                b       main

Ich hab von Assembler nicht viel Ahnung. Wenn ich den Code richtig 
verstehe, wird die data Section hier ins Ram kopiert.

Zu Punkt 2:

Das ganze sollte also so aussehen:
void foo(void) __attribute__ ((section ("data")));


Soweit verstehe ich das ganze noch. Mit dem Attribut der der Compiler 
angewiesen, die Funktion in dem Bereich abzulegen, in dem die Variablen 
im Ram liegen. Im Startup-Code wird dann die Funktion vom Flash ins Ram 
kopiert.


Zu Punkt 3:

Es soll ein Pointer verwendet werden, um die Funktion anzusprechen, also
z.B.:
void *foopointer = &foo;
foopointer();


So, jetzt meine Fragen:
Funktioniert das ganze so wirklich?
Wofür wird der Umweg über den Pointer benötigt?

Vielen Dank,

Tilo

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das beantwortet Karl Olsen in der gleichen Diskussion:

Nice trick of just locating the RAM function in .data.

With main() in flash and IAP_Test() in RAM, they are ~1GB apart, and
a normal BL instruction can only handle distances of up to +/- 32 MB.
Try calling it indirectly:

static void (*pramfunc)(void) = IAP_Test;
(*pramfunc)();

Dirch den Funktionszeiger soll Maschinencode erzeugt werden, der sog. 
long calls ermöglicht. Nicht die üblichen, platzsparenderen short calls 
innerhab der üblichen Flash-Adressbereiche.

Autor: Martin Thomas (mthomas) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Evtl. einfacher: _attribute_ ((long_call, section (".data"))) und 
Funktion wie üblich aufrufen.

Autor: Tilo L. (katagia)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für eure Antworten.

Das hier funktioniert:
..
void DAC_Aquiredata(void) __attribute__ ((section (".data")));

void DAC_Aquiredata(void) {
...

Das hier hingegen nicht:
..
void DAC_Aquiredata(void) __attribute__ ((long_call, section (".data")));

void DAC_Aquiredata(void) {
...

dac.c:96: error: conflicting types for 'DAC_Aquiredata'
dac.h:6: error: previous declaration of 'DAC_Aquiredata' was here


So, nun bin ich etwas verwirrt. Unter 
http://www.siwawi.arubi.uni-kl.de/avr_projects/arm...
habe ich ei Beispiel gefunden. Ich verwende einen aduc, das Beispiel ist 
für einen lpc. Sollte aber dem GCC egal sein.

In diesem Beispiel wurde das so gemacht:
#define FASTRUN __attribute__ ((long_call, section (".data")))

extern FASTRUN void setLED1(int on);
FASTRUN void setLED1(int on)

{

Das funktioniert so bei mir auch. Leider gibt der Compiler eine Warnung 
aus:
Warning: ignoring changed section attributes for .data
Laut http://www.spinics.net/lists/arm-kernel/msg24864.html ist das so, 
da in diesem Bereich kein Code ausgeführt werden darf. Das kann ich in 
diesem Fall dann acuh nachvollziehen. Ich weiß aber nicht, warum das so 
ist. Muss irgend wo noch markiert werden, welcher Code ausgeführt werden 
darf?

Ich hab die von mir verwendete Datei, in der die Sektionen definiert 
sind, angehängt. Sieht da einr von euch etwas dran?

Fehlt eine Option in der Makefile?

Danke, Tilo

Autor: Karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Keine Datei dabei. Ich rate mal: Im Linkerscript haben die einzelnen 
Bereiche die Attribute r,w,x.
MEMORY
{
  FLASH (rx) : ORIGIN = 0x00100000, LENGTH = 0x00040000
  DATA (rw)  : ORIGIN = 0x00200000, LENGTH = 0x00010000
  STACK (rw) : ORIGIN = 0x00210000, LENGTH = 0x00000000
}

stammt zwar aus nem AT91 script, aber das soll mal nicht stören.

Autor: Tilo L. (katagia)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Ich habe den Dateianhang leider vergessen.
Im Linkerskript sind die Speicherbereiche so definiert:
MEMORY 
{
  /* flash  : ORIGIN = 0x00080000,          LENGTH = 62K    /* FLASH EPROM, the last 2K are used for the bootloader    */  
  flash  : ORIGIN = 0x0,          LENGTH = 62K    /* FLASH EPROM, the last 2K are used for the bootloader    */  
  ram  : ORIGIN = 0x00010000, LENGTH = 8K    /* static RAM area  */
}

rw ist nirgends angegeben. Die Data-Sektion sieht jetzt so aus:
  .data :                /* collect all initialized .data sections that go into RAM  */ 
  {
    _data = .;            /* create a global symbol marking the start of the .data section  */
    *(.data)            /* all .data sections  */
    *(.ramrun)            /* Section for functions which should be load to ram */
    _edata = .;            /* define a global symbol marking the end of the .data section  */
  } >ram AT >flash                /* put all the above into RAM (but load the LMA initializer copy into FLASH)  */

.data konnte ich nicht verwenden. Also legte ich einen zusätzlichen 
Bereich .ramrun an. Damit funktioniert das ganze nun.

Autor: Veikko Werner (fischbohne)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

da bin ich ja über etwas interessantes gestolpert...

Muß man beim GCC etwas beachten -mlong-calls  o.Ä.

Gruß,
fischbohne

Autor: Tilo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Also ich hab keine speziellen Parameter in der Makefile drin. (GCC 
4.2.2)

Ich wollte einen Sinus (DSS) über einen DAC ausgeben. Auf dem Oszi hat 
man deutlich gesehen, dass (bei mir) SRAM deutlich schneller als FLASH 
ist.

Autor: Martin Thomas (mthomas) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
-mlong-calls is meines Wissens in "pauschales" _attribute_ (long_call) 
für alle Funktionen und dürfte ein wenig an der Performance knabbern. 
Ist allerdings die simpelste Lösung, um um die Sprungweitenbegrenzung 
herumzuarbeiten. Selektiver mit dem o.g. Ansatz.

BTW: in einem der Beträge oben:
>dac.c:96: error: conflicting types for 'DAC_Aquiredata'
>dac.h:6: error: previous declaration of 'DAC_Aquiredata' was here
sieht nach Unterschied in Deklaration (.h) und Definition (.c) der 
Funktion aus. Aber Problem hat sich ja schon vor längerem in 
wohlgefallen aufgelöst.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.