ARM7 - Funktionen ins Ram kopieren

Gast #837792
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:
1
        /* copy initialized variables .data section  (Copy from ROM to RAM) */
2
                ldr     R1, =_etext
3
                ldr     R2, =_data
4
                ldr     R3, =_edata
5
1:            cmp     R2, R3
6
                ldrlo   R0, [R1], #4
7
                strlo   R0, [R2], #4
8
                blo     1b
9

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

18
        /* Enter the C code  */
19
                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:
1
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.:
1
void *foopointer = &foo;
2
foopointer();


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

Vielen Dank,

Tilo
Persönliche Seite
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.
Gast
Danke für eure Antworten.

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

4
void DAC_Aquiredata(void) {
5
...

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

4
void DAC_Aquiredata(void) {
5
...

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_projects/index.html#gcc_ramfunc
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:
1
#define FASTRUN __attribute__ ((long_call, section (".data")))
2

3
extern FASTRUN void setLED1(int on);
4
FASTRUN void setLED1(int on)
5

6
{

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
Gast
Keine Datei dabei. Ich rate mal: Im Linkerscript haben die einzelnen 
Bereiche die Attribute r,w,x.
1
MEMORY
2
{
3
  FLASH (rx) : ORIGIN = 0x00100000, LENGTH = 0x00040000
4
  DATA (rw)  : ORIGIN = 0x00200000, LENGTH = 0x00010000
5
  STACK (rw) : ORIGIN = 0x00210000, LENGTH = 0x00000000
6
}

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

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

rw ist nirgends angegeben. Die Data-Sektion sieht jetzt so aus:
1
  .data :                /* collect all initialized .data sections that go into RAM  */ 
2
  {
3
    _data = .;            /* create a global symbol marking the start of the .data section  */
4
    *(.data)            /* all .data sections  */
5
    *(.ramrun)            /* Section for functions which should be load to ram */
6
    _edata = .;            /* define a global symbol marking the end of the .data section  */
7
  } >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.
Gast
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.
Moderator Persönliche Seite
-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

Eine eigene Frage? Dieser Thread ist über 18 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.