Forum: Compiler & IDEs "Apps" für ein embedded Device


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Christopher (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen!

Ich würde gerne auf meinen STM32 sowas wie Apps realisieren.
Auf dem Controller läuft die Ablaufumgebung. Die "Apps" sollen von 
SD-Karte dann (an beliebiger freier) ins RAM geladen und von dort 
ausgeführt werden. Dabei nutzen die Apps logischer Weise auch Code aus 
dem Flash...
Letzeres habe ich mir gedacht löse ich einfach damit, dass ich einfach 
alle Funktionspointer beim starten der App aus dem RAM dieser als 
Callback mitgebe. Zudem soll die App dann als eigener Task/Thread des 
RTOS laufen.
Was mir noch nicht klar ist:
Wie erstelle ich solche Apps? Also wie muss ich sie linken?!? ich weiß 
ja nie, an welcher Stelle sprich Speicheradresse die App später im RAM 
liegen wird! :-O
Wie rufe ich sie richtig auf?

hoffe ihr könnt mir helfen!?!

Danke und Grüße
Christopher

von Rufus Τ. F. (rufus) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Das Stichwort lautet "relocatable code".

von Vincent H. (vinci)


Bewertung
0 lesenswert
nicht lesenswert
Das Stichwort lautet Lua, Python oder JS...

/edit
Oder für hartgesottene Forth ;)

: Bearbeitet durch User
von Guest (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Welches RTOS benutzt du denn?

von Christopher (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Rufus Τ. F. schrieb:
> Das Stichwort lautet "relocatable code".

Bei der Onlinesuche lande ich mehr oder weniger hier:
https://de.wikipedia.org/wiki/Position-Independent_Code
Und das der Lader die Adressen passen muss...
Und woher weiß ich wo die Adressen im Code liegen, die ich ändern muss?
und worauf beziehen die sich? Offset?

Vincent H. schrieb:
> Das Stichwort lautet Lua, Python oder JS...

Auf einem Cortex-M4!?

Guest schrieb:
> Welches RTOS benutzt du denn?

FreeRTOS

von Rufus Τ. F. (rufus) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Christopher schrieb:
> Und das der Lader die Adressen passen muss...

Adressen müssen nur angepasst werden, wenn das kein relocatable code 
ist. Es gibt Prozessorarchitekturen, bei denen das der Fall ist, da muss 
dann der Code mit einer entsprechenden "Patchtabelle" ausgestattet 
werden, die der Lader abarbeiten kann. So wird es beispielsweise auf 
x86-Systemen gehandhabt.

Andere Prozessorarchitekturen kennen vollständig verschiebbaren Code, 
der läuft, egal an welche Speicheradresse er geladen wird (sofern man 
gewisse Alignmentvorgaben einhält). Das ist beispielsweise beim 68k der 
Fall, oder schon deutlich früher bei 6800 bzw. 6502 möglich gewesen.

Voraussetzung ist halt, daß nicht nur Programmsprünge und -Verzweigungen 
relativ zum PC adressiert werden, sondern daß auch Speicherzugriffe 
relativ zu einer in ein Prozessorregister geladenen Basisadresse 
ausgeführt werden, also der Prozessor entsprechende indirekte und 
indizierte Adressierungsarten beherrscht.

ARMe sind wohl nicht mit dieser Designvorgabe entwickelt worden.

von Kaj (Gast)


Bewertung
1 lesenswert
nicht lesenswert
Christopher schrieb:
> Vincent H. schrieb:
>> Das Stichwort lautet Lua, Python oder JS...
>
> Auf einem Cortex-M4!?
Ja, und? Gibt doch microPython
http://micropython.org/

von Vincent H. (vinci)


Bewertung
1 lesenswert
nicht lesenswert
Christopher schrieb:
> Vincent H. schrieb:
>> Das Stichwort lautet Lua, Python oder JS...
>
> Auf einem Cortex-M4!?

Natürlich.

eLua
http://www.eluaproject.net/

MicroPython
https://micropython.org/

JS
https://www.espruino.com/

Forth
http://mecrisp.sourceforge.net/

von Joerg W. (joergwolfram)


Bewertung
0 lesenswert
nicht lesenswert
Solange immer nur eine "App" laufen soll, ist das kein Problem, da der 
Adressbereich fix ist. Ich hatte das schon mal für eine andere 
Architektur (S12X) gemacht.

- Im Linkerscript für das "OS" wird das RAM so angegeben, dass der für 
die APP benötigte Bereich gar nicht existiert. Um Daten dorthin zu 
bekommen, benutzt man einfach Pointer.

- Im Linkerscript für die "App" gibt es nur den einen Bereich, nämlich 
den im RAM. Dort landen dann alle Segmente.

- Funktionen im Flash werden über eine Sprungtabelle an festgelegter 
Adresse im Flash realisiert. Dazu gibt es passend eine ASM-Library, die 
nur die entsprechenden Sprünge zu den Funktionen enthält. Diese Library 
wird anstelle der "normalen" Library zu den Apps gelinkt. Die 
Sprungtabelle  kann man z.B. an den Startup-Code oder die Vektortabelle 
anhängen.


Schwieriger wird es, wenn mehrere dieser Apps quasi gleichzeitig laufen 
sollen. Hier müsste man wohl oder übel beim Laden relozieren oder der 
Controller hat eine MMU bzw. man kann über Bankswitching tricksen 
(S12XE).

Die zweite Möglichkeit ist, einen Interpreter für eine höhere 
Programmiersprache/Scriptsprache zu benutzen, wie in den Beiträgen 
weiter oben.

Als dritte Möglichkeit könnte man auch eine andere Architektur 
emulieren. Beim AX81 habe ich z.B. einen Z80 im AVR emuliert, bei meinem 
aktuellen Projekt (noch nicht veröffentlicht, da noch lange nicht 
fertig) ist es eine PDP11-CPU. Compiler gibt es für diese Architektur ja 
noch genug (GCC, CC, PCC). Wenn man dann gleich noch eine MMU mit 
implementiert, lassen sich auch ohne Probleme Host-Flash oder I/O mit in 
den Adressraum der Gast-CPU mappen.

Jörg

von Christopher (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Vincent H. schrieb:
> Natürlich.
>
> eLua
> http://www.eluaproject.net/
>
> MicroPython
> https://micropython.org/
>
> JS
> https://www.espruino.com/
>
> Forth
> http://mecrisp.sourceforge.net/

Was es nicht alles gibt!

Joerg W. schrieb:
> Schwieriger wird es, wenn mehrere dieser Apps quasi gleichzeitig laufen
sollen.

Nicht nur "quasi". - Sie sollen! ;-)

von Joerg W. (joergwolfram)


Bewertung
0 lesenswert
nicht lesenswert
Wenn mehrere Apps nicht nur "quasi" !gleichzeitig! laufen sollen, 
brauchst Du mehrere Kerne...

"Beliebige Adressen im RAM" halte ich für extrem aufwändig, weil 
letztendlich die fertige App auf dem STM32 gelinkt werden müsste.

Abhängig von der Größe des RAM würden mir jetzt zwei Ideen einfallen:

internes RAM
------------------------
Da die Apps im Vergleich zur Größe der SD-Karte recht winzig sind, 
könnte man verschiedene Versionen auf verschiedene Adressen (z.B. 
4K-Raster) linken und dann beim Laden entscheiden, welche Version 
genommen wird. Wenn man mit Makefiles arbeitet, lässt sich das Erstellen 
weitestgehend automatisieren.

externes RAM
------------------------
Hier könnte man mit einee kleinen zusätzlichen Logik eine 
Bankumschaltung realisieren. Das "verschwendet" zwar Speicher, ist aber 
recht einfach zu realisieren. Vor allen Dingen sind dadurch die 
einzelnen Tasks gut voneinander isoliert, wobei eine Fehlfunktion in 
einer App ohne MMU/MPU trotzdem das ganze System zerschießen kann.

Wenn das Ganze nicht nur für Dich ist und einigermaßen robust sein soll, 
kommst Du meiner Meinung nach um einen Controller mit MMU/MPU oder 
Interpreter/Emulation nicht drumherum.

Jörg

von Markus F. (mfro)


Bewertung
0 lesenswert
nicht lesenswert
Ich hab's noch nie probiert, aber die gängigen ARM-Compiler sollten 
eigentlich PIC- (position independent) Code erzeugen können.

Dazu müsstest Du dir dann wohl eine Art Loader schreiben.

Das wird's wohl noch nicht gewesen sein. Zusätzlich muß wahrscheinlich 
das Linkerscript angepaßt werden (da kommen ein paar neue Sections 
hinzu) und (falls verwendet) müssen Libraries mit -fPIC neu compiliert 
werden.

Wie gesagt, auf ARM habe ich's noch nie selbst probiert, aber gehen 
müsste das eigentlich schon.

von eagle user (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Der gcc kann es im Prinzip, er erzeugt dann eine Global Offset Table und 
mehr relative Adressierung. Er akzeptiert zwei äußerst interessante 
Optionen
1
-msingle-pic-base
2
Treat the register used for PIC addressing as read-only, rather than loading it in the prologue for each function. The runtime system is responsible for initializing this register with an appropriate value before execution begins.
1
-mpic-data-is-text-relative
2
Assume that the displacement between the text and data segments is fixed at static link time. This permits using PC-relative addressing operations to access data known to be in the data segment. For non-VxWorks RTP targets, this option is enabled by default. When disabled on such targets, it will enable -msingle-pic-base by default.
Aber die Wirkung ist seltsam. Dieses PIC base register ist nicht zu 
sehen, er packt dann static const Daten (z.B. Texte) ins RAM, die normal 
im Flash landen und die Offset Table ist bei einem 24K Programm nur 48 
Byte groß?? Andererseits, warum braucht er überhaupt noch eine Offset 
Table?
1
void
2
btx_clear_screen (const btx_struct *menu)
3
{
4
   clear_screen ();
5
   printf ("%s ", menu->title);
6
}
diese Funktion "normal" übersetzt:
1
20008434 <btx_clear_screen>:
2
20008434:       b510            push    {r4, lr}
3
20008436:       4604            mov     r4, r0
4
20008438:       f7fa ff02       bl      20003240 <clear_screen>
5
2000843c:       6961            ldr     r1, [r4, #20]
6
2000843e:       4802            ldr     r0, [pc, #8]    ; (20008448 <btx_clear_screen+0x14>)
7
20008440:       e8bd 4010       ldmia.w sp!, {r4, lr}
8
20008444:       f7fa bfa4       b.w     20003390 <printf>
9
20008448:       2000d656        .word   0x2000d656

und mit "-fpic -msingle-pic-base -mpic-data-is-text-relative":
1
20008478 <btx_clear_screen>:
2
20008478:       b510            push    {r4, lr}
3
2000847a:       4604            mov     r4, r0
4
2000847c:       f7fa fee0       bl      20003240 <clear_screen>
5
20008480:       4803            ldr     r0, [pc, #12]   ; (20008490 <btx_clear_screen+0x18>)
6
20008482:       6961            ldr     r1, [r4, #20]
7
20008484:       4478            add     r0, pc
8
20008486:       e8bd 4010       ldmia.w sp!, {r4, lr}
9
2000848a:       f7fa bf81       b.w     20003390 <printf>
10
2000848e:       bf00            nop
11
20008490:       00004b3e        .word   0x00004b3e

printf() und clear_screen() stehen dabei schon im Flash, 20003xxx sind 
die Einträge in der Sprungtabelle.

von Markus F. (mfro)


Bewertung
0 lesenswert
nicht lesenswert
eagle user schrieb:
> Aber die Wirkung ist seltsam.

Wenn ich das richtig sehe, hast Du mit -O2 compiliert?

Da ist wahrscheinlich das meiste, was der gcc für -fPIC "dazugetan" hat, 
schon wieder wegoptimiert, weil's in deinem Fall nicht gebraucht wird.

Probier' mal mit -O0, dann sieht man möglicherweise eher, was da anders 
ist.

von Rufus Τ. F. (rufus) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
eagle user schrieb:
> Dieses PIC base register ist nicht zu sehen, er packt dann static const
> Daten (z.B. Texte) ins RAM, die normal im Flash landen

Das aber ist doch logisch, wenn Programme als "Apps" zur Laufzeit ins 
RAM geladen werden sollen. Da kann und darf nichts im Flash landen.

von eagle user (Gast)


Bewertung
0 lesenswert
nicht lesenswert
o.k., das war missverständlich, ich sollte "text section" statt "Flash" 
und  "data section" statt "RAM" schreiben. Normal werden solche const 
Daten ja direkt aus dem Flash gelesen und nicht ins RAM umkopiert. Warum 
müssen die mit -fpic dann zweimal im RAM stehen? Wie doof das ist, sagt 
arm-none-eabi-size; normal ist:
1
   text    data     bss     dec     hex filename
2
  24276       0    1696   25972    6574 BUILD/display.elf
und mit pic:
1
   text    data     bss     dec     hex filename
2
  22436    2872    1696   27004    697c BUILD/display.elf

Markus F. schrieb:
> Probier' mal mit -O0, dann sieht man möglicherweise eher, was da
> anders ist.

Ich compile immer mit -Os, der Größenunterschied zu -O0 oder -O2 ist 
immens (-O0 -fpic):
1
   text    data     bss     dec     hex filename
2
  35551    4072    1696   41319    a167 BUILD/display.elf
und dieses Spezialregister sehe ich immer noch nicht:
1
200085fc <btx_clear_screen>:
2
200085fc:       b500            push    {lr}
3
200085fe:       b083            sub     sp, #12
4
20008600:       9001            str     r0, [sp, #4]
5
20008602:       f7fa fe1d       bl      20003240 <clear_screen>
6
20008606:       9b01            ldr     r3, [sp, #4]
7
20008608:       695b            ldr     r3, [r3, #20]
8
2000860a:       4619            mov     r1, r3
9
2000860c:       4b04            ldr     r3, [pc, #16]   ; (20008620 <btx_clear_screen+0x24>)
10
2000860e:       447b            add     r3, pc
11
20008610:       4618            mov     r0, r3
12
20008612:       f7fa febd       bl      20003390 <printf>
13
20008616:       bf00            nop
14
20008618:       b003            add     sp, #12
15
2000861a:       f85d fb04       ldr.w   pc, [sp], #4
16
2000861e:       bf00            nop
17
20008620:       0000560a        .word   0x0000560a



wenn man -fomit-frame-pointer vergisst, wird's auch nicht besser ;)
1
   text    data     bss     dec     hex filename
2
  35839    4072    1696   41607    a287 BUILD/display.elf
1
20008610 <btx_clear_screen>:
2
20008610:       b580            push    {r7, lr}
3
20008612:       b082            sub     sp, #8
4
20008614:       af00            add     r7, sp, #0
5
20008616:       6078            str     r0, [r7, #4]
6
20008618:       f7fa fe12       bl      20003240 <clear_screen>
7
2000861c:       687b            ldr     r3, [r7, #4]
8
2000861e:       695b            ldr     r3, [r3, #20]
9
20008620:       4619            mov     r1, r3
10
20008622:       4b04            ldr     r3, [pc, #16]   ; (20008634 <btx_clear_screen+0x24>)
11
20008624:       447b            add     r3, pc
12
20008626:       4618            mov     r0, r3
13
20008628:       f7fa feb2       bl      20003390 <printf>
14
2000862c:       bf00            nop
15
2000862e:       3708            adds    r7, #8
16
20008630:       46bd            mov     sp, r7
17
20008632:       bd80            pop     {r7, pc}
18
20008634:       00005714        .word   0x00005714

von W.S. (Gast)


Bewertung
2 lesenswert
nicht lesenswert
Christopher schrieb:
> Ich würde gerne auf meinen STM32 sowas wie Apps realisieren.
> Auf dem Controller läuft die Ablaufumgebung. Die "Apps" sollen von
> SD-Karte dann (an beliebiger freier) ins RAM geladen und von dort
> ausgeführt werden.

Ich schätze mal, daß dein Projekt in die Hose gehen wird.

Zunächst brauchst du resident im µC eine Art Betriebssystem, das die HW 
von den Apps trennt und verwaltet. Das ist der einfachste Teil. Ich 
hatte sowas vor langer Zeit in der Lernbetty vorexerziert.

Als API hat man da bei den ARM's den SVC, also den Supervisor-Call. Das 
ist ne recht effiziente Sache, bei der die App garnicht wissen muß, wo 
die angeforderte OS-Leistung erbracht wird. Allerdings ist der GCC für 
sowas zu blöd. Da sollte man den Keil nehmen, der beherrscht das 
prächtig. Wenn man partout den GCC nehmen will, braucht man nen 
Assembler-Wrapper dafür (gibt's auch bereits in der Lernbetty).

Alles, was bisher an Sprungleisten und so genannt wurde, ist dagegen nur 
umständlich und bringt nur zusätzliche Abhängigkeiten zwischen OS und 
App ins Spiel.

So, das war der leichte Teil.

Der weitaus schwierigere Teil ist die Forderung nach mehreren Apps zu 
gleicher Zeit im RAM. Das läuft auf ein selbstdefiniertes EXE-Format für 
die Apps hinaus, um dort die benötigten Relokations-Informationen 
unterzubringen. Dazu gehört natürlich auch eine Art Nachbrenner nach dem 
Linker, um so eine EXE-Datei zu generieren. Macht ne Menge Arbeit.

Von sowas wie positionsunabhängigem Code würde ich heftigst die Finger 
lassen - wer sich mit dem Eröffnungsbeitrag schon an das Forum wenden 
muß, wird das General-Geeiere im Code der Apps zum Auseinanderhalten von 
positionsabhängigen Daten und positionsunabhängigen Daten (jeweils 
inclusive Pointer-Turnerei) eher nicht erfolgreich absolvieren können.

W.S.

von eagle user (Gast)


Bewertung
0 lesenswert
nicht lesenswert
W.S. schrieb:

> Der weitaus schwierigere Teil ist die Forderung nach mehreren Apps zu
> gleicher Zeit im RAM. Das läuft auf ein selbstdefiniertes EXE-Format für
> die Apps hinaus, um dort die benötigten Relokations-Informationen
> unterzubringen. Dazu gehört natürlich auch eine Art Nachbrenner nach dem
> Linker, um so eine EXE-Datei zu generieren.

Das ELF-Format sollte für den Zweck ausreichen und der gcc hat 
anscheinend auch den passenden Nachbrenner dazu. Jedenfalls funktioniert 
es hier soweit, dass die LED blinkt und printf() über ein UART ausgeben 
kann.

Das ging so:
 * es gibt ein Blinkprogramm, das ab 0x20002000 im RAM läuft
 * man übersetzt es neu mit -fpic -msingle-pic-base
 * es wird deutlich größer, aber läuft immer noch ab 0x20002000
 * man lädt die unveränderte Hex-Datei nach 0x20003000
 * es funktioniert immer noch

Ja, das ist nur die halbe Miete. Globale Variablen funktionieren nicht, 
statische vielleicht auch nicht. Aber dafür haben gcc/ld eine global 
offset table und ein "base register(?)" (r9) eingebaut und printf() 
funktioniert. Jetzt muss man "nur" noch die Feinheiten verstehen, z.B. 
wie man r9 initialisieren muss. Das kann ja erst nach dem Laden von der 
SD-Karte passieren.

Im Flash steht momentan nur eine Art Boot Loader, der ein gültiges (CRC 
usw.) Programm im RAM sucht und startet.

Eine Hex-Datei enthält ja normalerweise feste Adressen, auch wenn sie 
mit -fpic erzeugt wurde. Mein Hex-Loader ignoriert die und lädt den 
unveränderten Inhalt woanders hin (also jetzt für den Versuch).

W.S. schrieb:
> Alles, was bisher an Sprungleisten und so genannt wurde, ist dagegen nur
> umständlich und bringt nur zusätzliche Abhängigkeiten zwischen OS und
> App ins Spiel.

Ja, es ist umständlich, aber wo wäre der Unterschied zum SVC? Man muss 
der "App" ja auch beibringen, welcher SVC was macht; die Abhängigkeit 
bleibt uns. Ich mache es so, dass die "App" nur Funktionen sieht, auch, 
wenn ein SVC drin steckt. Tatsächlich habe ich aus einem Funktionsaufruf 
per Sprungleiste einen SVC gemacht, ohne dass eine "App" etwas gemerkt 
hätte.

von Joerg W. (joergwolfram)


Bewertung
0 lesenswert
nicht lesenswert
Der SVC entspricht, soweit ich das verstanden habe, dem was "früher" 
Software-Interrupts und Traps waren.
Damit wechselt man beim Aufruf der System-Routine aus dem User- in den 
Supervisormodus. Richtig Nutzen hat man davon erst, wenn eine MMU/MPU 
mit im Spiel ist. Dann kann man nämlich dafür sorgen, dass eine "App" 
nur ihren eigenen Speicherbereich "sieht" und z.B. nicht auf die 
Hardware-Register oder Speicher anderer Tasks zugreifen kann.

Global Offset Table (GOT) muss auf den Anfang vom BSS zeigen. Die 
eigentliche Berechnung könnte man einfach in den Startup-Code 
integrieren. Also (aktuelle PC-Position) + (Größe Code-Segment) + (Größe 
Data-Segment) - (bereits "verbrauchte" Bytes im Startup-Code, das müsste 
man einmalig aus dem Disassembly des Startup-Codes bestimmen) -> R9

Jörg

von Markus F. (mfro)


Bewertung
0 lesenswert
nicht lesenswert
Joerg W. schrieb:
> Die
> eigentliche Berechnung könnte man einfach in den Startup-Code
> integrieren. Also (aktuelle PC-Position) + (Größe Code-Segment) + (Größe
> Data-Segment) - (bereits "verbrauchte" Bytes im Startup-Code, das müsste
> man einmalig aus dem Disassembly des Startup-Codes bestimmen) -> R9

Das läßt man m.E. besser das Linker-Script machen, wenn man keine 
unliebsamen Überraschungen mag.

von eagle user (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Joerg W. schrieb:

> Der SVC entspricht, soweit ich das verstanden habe, dem was
> "früher" Software-Interrupts und Traps waren.
> Damit wechselt man beim Aufruf der System-Routine aus dem User- in den
> Supervisormodus.

Das ist in gewisser Weise eine Nebenwirkung, für die App ist es vor 
allem eine Art Unterprogrammaufruf bei dem der Aufrufer die Zieladresse 
nicht kennen muss.

> Richtig Nutzen hat man davon [vom SVC] erst, wenn eine MMU/MPU
> mit im Spiel ist. Dann kann man nämlich dafür sorgen, dass eine "App"
> nur ihren eigenen Speicherbereich "sieht" und z.B. nicht auf die
> Hardware-Register oder Speicher anderer Tasks zugreifen kann.

Und ich sag' euch, das ist so dermaßen angenehm, wenn z.B. Null-Pointer 
sofort abgefangen werden und keine Folgefehler haben. Die unerlaubte 
Adresse und die des "bösen" Befehls werden angezeigt und stimmen fast 
immer auf das Byte genau. Das geht auch schon mit der MPU vom 
Cortex-M0+; den M0 ohne + sollte man garnicht mehr einsetzen.

> Global Offset Table (GOT) muss auf den Anfang vom BSS zeigen. Die
> eigentliche Berechnung könnte man einfach in den Startup-Code
> integrieren. Also (aktuelle PC-Position) + (Größe Code-Segment) + (Größe
> Data-Segment) - (bereits "verbrauchte" Bytes im Startup-Code, das müsste
> man einmalig aus dem Disassembly des Startup-Codes bestimmen) -> R9

Warum nicht einfach (Start Code-Segment) + (Größe Code-Segment) + (Größe 
Data-Segment)?

Markus F. schrieb:

> Das läßt man m.E. besser das Linker-Script machen, wenn man keine
> unliebsamen Überraschungen mag.

Man braucht wohl beides. Im Linker-Script vergibt man Namen für z.B. 
(Start des BSS) und der Startup-Code rechnet die aktuelle Position der 
App dazu und lädt R9. Das gleiche muss auch für den Stack Pointer 
gemacht werden.

von Felix F. (wiesel8)


Bewertung
0 lesenswert
nicht lesenswert
eagle user schrieb:
> Das ELF-Format sollte für den Zweck ausreichen und der gcc hat
> anscheinend auch den passenden Nachbrenner dazu. Jedenfalls funktioniert
> es hier soweit, dass die LED blinkt und printf() über ein UART ausgeben
> kann.
>
> Das ging so:
>  * es gibt ein Blinkprogramm, das ab 0x20002000 im RAM läuft
>  * man übersetzt es neu mit -fpic -msingle-pic-base
>  * es wird deutlich größer, aber läuft immer noch ab 0x20002000
>  * man lädt die unveränderte Hex-Datei nach 0x20003000
>  * es funktioniert immer noch
>
> Ja, das ist nur die halbe Miete. Globale Variablen funktionieren nicht,
> statische vielleicht auch nicht. Aber dafür haben gcc/ld eine global
> offset table und ein "base register(?)" (r9) eingebaut und printf()
> funktioniert. Jetzt muss man "nur" noch die Feinheiten verstehen, z.B.
> wie man r9 initialisieren muss. Das kann ja erst nach dem Laden von der
> SD-Karte passieren.
>
> Im Flash steht momentan nur eine Art Boot Loader, der ein gültiges (CRC
> usw.) Programm im RAM sucht und startet.
>
> Eine Hex-Datei enthält ja normalerweise feste Adressen, auch wenn sie
> mit -fpic erzeugt wurde. Mein Hex-Loader ignoriert die und lädt den
> unveränderten Inhalt woanders hin (also jetzt für den Versuch).


Könntest du den Code dazu mal hochladen, würde mich interressieren.

mfg

von ucLinux-User (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Warum nicht ucLinux nehmen und für eigene Zwecke total abspecken? Gibts 
für STM32F4 und F7 fertig?

von eagle user (Gast)


Angehängte Dateien:

Bewertung
1 lesenswert
nicht lesenswert
Felix F. schrieb:

> Könntest du den Code dazu mal hochladen, würde mich interressieren.

Der stammt von einem anderen Programm. Die crt0 daraus hab' ich für 
diesen Versuch missbraucht, sie heisst jetzt vdrive/crt-vdrive.c. Das 
soll mal ein Boot Loader werden. Der allererste Versuch dazu steht in 
boot/ bzw. im Flash. vdrive/BUILD/vdrive.s19 wird ins RAM geladen und 
von boot gestartet.

vdrive wird immer nach 0x20002000 gelinkt, im letzten Schritt erzeugt 
tools/elf-to-srec aus dem vdrive.elf ein vdrive.s19. Normal auch auf 
0x20002000, aber mit "export PIC_OFFSET=0x1000" vor dem make bekommt das 
.s19 Adressen ab 0x20003000.

Alles maximal unübersichtlich, viel Spaß damit...

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]
  • [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.