Vorcompilierte lib per linker in speziellen Adressbereich mit festen Adressen möglich?

Gast #6320173
Lesenswert?

hi
Ich habe eine vorcompilierte lib die recht groß ist.

Ist es möglich diese lib in einen definierten FLASH Bereich abzulegen
UND
dabei die Funktionen an bestestimmte Adressen zu legen?

Ziel soll sein das man nicht immer die komplette SW neu aufspielen muss 
.. sondern nur die eigentliche Anwendung.

Funktionen in einen bereich ablegen ist soweit kein thema.
NUR wird das jedesmal neu compiliert.

Mir entzieht sich momentan die kenntnis wie man die
Adressen exportieren kann..
Ebenso bräuchte ich da dann für die finale SW einen tabelle an welcher 
adresse welche funktion liegt ... richtig?

Idee beim schreiben :
1: die lib in einen FLASH block legen + compilieren ( wie am besten )
2: man exportiert die adressen aus der compilierten lib ( mapfile )
3: ein headerfile was funktionen auf die adressen mappt

dieses headerfile muss immer für diese lib/projekt genutzt werden
Gast #6320260
Lesenswert?

Ich habe das mal für den "inoffiziellen" oberen 64k Bereich eines 
BluePill gemacht.

Im linker script habe ich ein "UPPER64K" Memory angelegt und in dessen 
section die Funktionen aufgelistet.

Die Funktionen lassen sich dann in einer Header Datei mit "extern" 
aufrufen.
#6320305
Lesenswert?

Für maximale Geschwindigkeit bei minimalem Flash-Bedarf: Beim Linken der 
lib erzeuge ich ein Mapfile und kopiere die Adressen der Funktionen in 
eine Assembler-Quelle. Diese Datei wird zusammen mit meinem 
Hauptprogramm übersetzt und gelinkt. Das Programm benutzt ansonsten ganz 
normale C-Header für die Funktionen der lib und beim Linken wären die 
Adressen der Funktionen zunächst undefined.

Man darf nur nicht vergessen, nach einer Änderung der lib das 
Hauptprogramm auch neu zu linken. Das geht, weil die lib nur selten neu 
übersetzt wird, ansonsten braucht es eine "Symboltabelle" im Flash. Ein 
reine lib sollte kein SVC benutzen, wie würde das mit einem RTOS o.ä. 
zusammen spielen?
Gast #6321274
Lesenswert?

hi

Danke nochmal für den schubser

Hatte gestern schon die lib an einer fixen stelle im Flash.
Leider klappte das compilieren der Anwendung noch nicht so richtig.
Ist fleißarbeit...
Zumindest habe ich jetzt eine Option wie man es machen könnte.
Gast #6322476
Lesenswert?

Bei IAR gibt es ein Tool isymexport.exe das aus einer elf-Datei die 
Symbole exportiert und in eine lib erzeugt. Die kann man dann wie 
gewohnt zu seinem Code linken. Damit entfällt die Notwendigkeit einer 
Tabelle mit all den Konsequenzen. Allerdings muss die Zielapp jedesmal 
neu compiliert werden wenn sich an der lib was ändert.
Gast #6322485
Lesenswert?

Moin,
ich kämpfe gerade mit der oben erwähnten .h Datei.

Erstellt habe ich bis jetzt eine App1, die beim BluePill die 
Funktions-Adressen-Tabelle und 3 Funktionen ab 0x08010000 ablegt.
Funktioniert alles.

In einer App2 möchte ich diese nutzen. Das Linker Script möchte ich 
nicht ändern. Das hatte ich vor einiger Zeit mal probiert und das hat 
funktioniert. Hier möchte ich aber einfach nur die .h Datei in App2 
einfügen um auf die Tabelle und die Funktionen zuzugreifen.
Den oberen Bereich lediglich lesen und sonst nicht anfassen.

Mit:

#define FNTABLE_OFFSET (uint32_t)0x08010000
uint32_t *fntable=(uint32_t *)FNTABLE_OFFSET;

habe ich einen Zeiger auf die Tabelle und kann mit

  uint32_t a=fntable[0x00];
  uint32_t b=fntable[0x01];
  ....

die Adressen der Funktionen lesen.

Mit allerhand Pointer Experimenten habe ich es nicht geschafft, einen 
Funktionsnamen, ohne Beachtung von Parametern und Rückgabewert, auf die 
richtige Adresse im oberen Bereich zu setzen.
Habe ich in der .ld schon mal vor einiger Zeit gemacht, damit war es mit 
extern ganz einfach und hat funktioniert.

Also die Frage ist:
wie verbinde ich den blanken Funktionsnamen ohne Parameter mit der 
Adresse aus der Funktionstabelle?
#6322728
Lesenswert?

pegel schrieb:
> wie verbinde ich den blanken Funktionsnamen ohne Parameter mit der
> Adresse aus der Funktionstabelle?

Am einfachsten fand ich dieses, das ist eine c-Datei, die wird bei der 
App2 ganz normal mit übersetzt
1
// lib.c 2020-02-28 23:04:40
2
  
3
// DO NOT EDIT -- generated from ../include/syslib.h by mk-lib-tables
4

5
__asm__ (" SYSLIB_VERSION = 0x5E598E78\n .global SYSLIB_VERSION ");
6

7
__asm__ (" abs            = 0x08008078\n .global abs            ");
8
__asm__ (" adc_init       = 0x08008080\n .global adc_init       ");
9
__asm__ (" adc_read       = 0x08008088\n .global adc_read       ");
10
__asm__ (" atoi           = 0x08008090\n .global atoi           ");
11
__asm__ (" beep           = 0x08008098\n .global beep           ");

die syslib.h ist noch normaler, da steht nichts spezielles drin:
1
int   abs (int i);
2
void  adc_init (void);
3
int   adc_read (int channel);
4
int   atoi (const char *text);
5
void  beep (int mHz, int ms);

Die Tabelle in der lib beginnt in diesem Fall auf 0x08008070. Die ersten 
8 Byte sind die Versionsnummer, dann folgen Sprungbefehle zu den 
eigentlichen Funktionen, deshalb sind es 8 Byte pro Funktion. Das ist 
auch wieder Assembler in c verpackt:
1
// lib-table.c 2020-02-28 23:04:40
2

3
// DO NOT EDIT -- generated from ../include/syslib.h by mk-lib-tables
4

5
void __attribute__ ((naked, section ("$syslib_table"), aligned (16)))
6
lib (void)
7
{
8
 __asm__ (" SYSLIB_VERSION = 0x5E598E78\n .global SYSLIB_VERSION");
9
 __asm__ ("lib: .word 0x5E598E78");
10
 __asm__ ("     .word 0xFFFFFFFF");
11

12
 __asm__ ("  ldr pc, [pc]\n  .word   abs        ");
13
 __asm__ ("  ldr pc, [pc]\n  .word   adc_init   ");
14
 __asm__ ("  ldr pc, [pc]\n  .word   adc_read   ");
15
 __asm__ ("  ldr pc, [pc]\n  .word   atoi       ");
16
 __asm__ ("  ldr pc, [pc]\n  .word   beep       ");
#6322834
Lesenswert?

Das unterste Bit der Adresse muss gesetzt sein, sonst versucht der 
Prozessor das Instruction Set zu wechseln (was er nicht kann) und löst 
eine Exception aus. Im Normalfall sorgt der Compiler dafür dass das Bit 
bei einem Sprung gesetzt wird, in dem Fall aber anscheinend nicht weil 
er die absolute Adresse direkt bekommt...?
Gast #6908507
Lesenswert?

Hi,
ich hätte noch eine Frage.
1
void Init_up64k(){
2
  {__asm__ (" LedOn            = 0x0801001D\n .global LedOn             ");}
3
...

Es läuft alles wie es soll. Nur eines hätte ich gern noch.
Ab Adresse 0x08010000 habe ich eine Tabelle mit den Adressen der 
Funktionen.
Ich würde gern für LedOn nicht die Funktionsadresse selbst, sondern den 
Wert aus der Tabelle - Adresse steht in 0x0801000 - eintragen.
Kann mir jemand verraten wie das mit _asm_ geht?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren